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
497status, 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 useshttp://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
- 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 withssl. The front-end sends cleartext to a port that demands TLS. The scheme inproxy_pass(or the target group protocol on an ALB) is wrong, not the certificate. - 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.
- A person or script hit
http://on an HTTPS-only port — A stale bookmark, a hardcodedhttp://link, a curl command withouthttps://, or a client pointed athttp://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 whilehttp://on the same port fails? If yes, TLS is healthy and the problem is a cleartext request reaching the TLS listener. - Check every
proxy_passand upstream definition in front of this nginx. A TLS port must be addressed asproxy_pass https://...;, nothttp://...;. 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 theserverblock 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_passscheme 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.