Problem

Requests to your site fail with 497 HTTP Request Sent to HTTPS Port, or the response body reads 400 Bad Request — The plain HTTP request was sent to HTTPS port. The number 497 shows up in your nginx access.log, in a proxy_pass error, or in a health-check dashboard.

Symptoms

  • nginx logs a 497 status, or returns a 400 whose body is literally “The plain HTTP request was sent to HTTPS port.”
  • The site works when you type https:// but breaks the moment something uses http:// against the same port.
  • A reverse proxy, load balancer, or ingress in front of nginx started returning 502/400 after a TLS change.
  • A monitoring probe or health check on port 443 (or a custom port like 8443) reports failure while the browser is fine.

What This Error Actually Means

497 is nginx telling you the exact opposite of a certificate problem. TLS is configured. The listener has the ssl keyword, the certificate is loaded, the handshake would work — but the bytes that arrived weren’t a TLS handshake at all. They were a plaintext HTTP request: GET / HTTP/1.1\r\nHost: .... nginx reads the first bytes, sees an ASCII request line where it expected a TLS ClientHello, and refuses. Rather than emit a misleading TLS error, it raises its own code — 497 — and answers with a 400.

This is the reverse of SSL_ERROR_RX_RECORD_TOO_LONG. That error is a client speaking TLS to a port answering in cleartext. 497 is a client speaking cleartext to a port expecting TLS. In both cases someone got the scheme wrong; 497 just means nginx is the one that noticed, on the TLS side.

The important consequence: the fault is almost never in nginx’s TLS setup. It’s upstream of the ssl listener — a proxy forwarding http:// to an https:// backend, a health check pointed at the wrong scheme, or a person hitting http://host:443.

Top 3 Causes

  1. A reverse proxy or load balancer forwards plain HTTP to a TLS port — The most common cause in production. An upstream terminates TLS, then does proxy_pass http://backend:443; to an nginx that listens with ssl. The front-end sends cleartext to a port that demands TLS. The scheme in proxy_pass (or the target group protocol on an ALB) is wrong, not the certificate.
  2. A health check or monitor uses the wrong scheme — An uptime probe, Kubernetes readiness check, or ELB health check is configured for HTTP on a port that only speaks HTTPS. The service is healthy; the probe is lying because it knocks in cleartext.
  3. A person or script hit http:// on an HTTPS-only port — A stale bookmark, a hardcoded http:// link, a curl command without https://, or a client pointed at http://host:8443. Harmless individually, but noisy in logs and confusing when a script fails silently.

Diagnose with DechoNet

  • SSL Check to confirm the port actually presents a valid certificate and completes a TLS handshake. If SSL Check succeeds, TLS is fine and the 497 is coming from a cleartext request in front of nginx — not from your certificate.
  • Port Check to verify the port is open and reachable, so you can separate “wrong scheme” from “nothing listening.”
  • HTTP Check against the https:// URL to confirm the app responds correctly over TLS, isolating the fault to whatever is sending plaintext.

Resolution Checklist

  • Confirm the pattern: does https:// work while http:// on the same port fails? If yes, TLS is healthy and the problem is a cleartext request reaching the TLS listener.
  • Check every proxy_pass and upstream definition in front of this nginx. A TLS port must be addressed as proxy_pass https://...;, not http://...;. On an AWS ALB/NLB, set the target group protocol to HTTPS.
  • Check health-check and monitor configuration: a probe on 443 (or your TLS port) must use the HTTPS scheme, or it will trip 497 forever while the service is fine.
  • For genuine client typos on an HTTPS-only port, add error_page 497 =301 https://$host$request_uri; inside the server block to redirect stray plaintext requests. Do this only after ruling out a proxy misconfiguration — it will loop if the front-end is the one sending cleartext.
  • Run SSL Check to confirm the handshake completes; if it does, stop looking at the certificate and go fix the scheme upstream.

When to Escalate

  • Escalate to whoever owns the load balancer or ingress if SSL Check shows a healthy certificate on the origin but 497s persist — the plaintext request is being generated between the edge and nginx, and the proxy_pass scheme or target-group protocol is the lever.
  • If 497 started right after a certificate install or a migration, suspect a front-end that was switched to talk to the new TLS port but is still configured to send http://.

Check your own domain now

Free, no sign-up. Runs the exact check this guide describes and shows what to fix.