< HTTP/1.1 497 HTTP Request Sent to HTTPS Port497 HTTP Request Sent to HTTPS Port (nginx)
nginx 497 means plain HTTP hit an HTTPS port; clients see "400 The plain HTTP request was sent to HTTPS port". Fix with error_page 497. Also 494, 495, 496.
- Cacheable
- No
- Retry?
- No: use https:// or redirect with error_page 497
- Usually sent by
- nginx (sent to the client as 400)
- Often confused with
- 400
TL;DR: 497 is nginx’s internal code for “a plain HTTP request arrived on a TLS port”. The client sees
400 Bad Requestwith the body “The plain HTTP request was sent to HTTPS port”. Usehttps://or adderror_page 497 =301 https://$host:$server_port$request_uri;to redirect.
What it means
When a listen ... ssl socket receives bytes that are not a TLS handshake, nginx has already parsed them as an HTTP request. If the connection has no TLS, the request is finalized with its internal NGX_HTTP_TO_HTTPS code, 497. The nginx source comment says the code exists to tell this case apart from an ordinary 4xx during error-page redirection. By default the response uses a 400 status line and this body (from ngx_http_special_response.c):
HTTP/1.1 400 Bad Request
Server: nginx
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
Because the status is 400, you search the web for that sentence, not for 497. The nginx docs describe it as “a regular request has been sent to the HTTPS port”. The error log, at info level, records client sent plain HTTP request to HTTPS port.
Who sent it?
An nginx whose listening socket has TLS enabled. The page is nginx’s own (with its Server: nginx header), even when the request reached it through a proxy. A common trap: nginx A proxies to nginx B with proxy_pass http://b:443;. The 400 text then comes from B, and A passes it on.
Fix it
-
Use the right scheme.
http://example.com:443/produces this error;https://example.com/does not. Check bookmarks, hard-coded URLs, health checks and webhooks configured withhttp://and port 443. -
Fix the proxy hop. If nginx proxies to a TLS backend:
location / { proxy_pass https://backend.internal:443; proxy_set_header Host $host; }With
proxy_pass http://backend.internal:443;the backend receives plaintext on its TLS port. In Kubernetes ingress-nginx, the matching annotation isnginx.ingress.kubernetes.io/backend-protocol: "HTTPS". -
Redirect instead of failing. If you deliberately serve HTTPS on a non-standard port and people type
http://:server { listen 8443 ssl; server_name example.com; error_page 497 =301 https://$host:$server_port$request_uri; }The nginx docs note the redirect happens after the request is fully parsed, so
$request_uri,$uriand$argsare available. For ports 80 and 443 use a separatelisten 80block that returns 301 and add HSTS. -
Load balancers and health checks. Make sure the backend protocol matches what the port speaks. A health check or backend configured for HTTP and pointed at an HTTPS port gets exactly this 400 response.
-
Redirect loops. If you add the 497 redirect and the browser reports too many redirects, a proxy in front is likely stripping TLS; see ERR_TOO_MANY_REDIRECTS.
Reproduce
curl -i http://example.com:443/
A plain-HTTP request to a TLS port returns the 400 page above. Compare with curl -I https://example.com/ for the working case.
494, 495 and 496
The same block of nginx-internal codes (NGX_HTTP_NGINX_CODES, starting at 494) contains three siblings. Defaults send a 400 status to the client for each, with a distinct message in the body, and each can be matched by error_page:
| Code | Body text nginx sends | When |
|---|---|---|
| 494 | Request Header Or Cookie Too Large | A request header line or the header block exceeds client_header_buffer_size and large_client_header_buffers (default 4 buffers of 8k). Oversized cookies are the usual cause. |
| 495 | The SSL certificate error | Client certificate verification failed with ssl_verify_client on or optional. |
| 496 | No required SSL certificate was sent | ssl_verify_client on and the client presented no certificate. |
For 494, nginx answers 400 where RFC 6585 would suggest 431. Fix it by shrinking cookies or raising large_client_header_buffers 4 16k;. For 495 and 496, a custom page can explain the problem to users:
error_page 495 496 /client-cert-error.html;
nginx documents 495, 496 and 497 in the ssl module; 494 appears in the source and in the large-header handling, not in that list.
Frequently asked questions
What does "400 The plain HTTP request was sent to HTTPS port" mean?
A client spoke plain HTTP to a port where nginx expects TLS. nginx recognises that, finalizes the request with its internal code 497, and sends a 400 Bad Request page by default. The fix is to use https:// in the URL or to redirect, not to change the server certificate.
Is 497 an official HTTP status code?
No. It is one of the internal codes nginx defines (494 to 497), defined in the source so that error_page can match these conditions separately from an ordinary 400. By default the client receives a 400 status, not 497.
How do I redirect HTTP to HTTPS on the same port with nginx?
Add error_page 497 =301 https://$host:$server_port$request_uri; to the TLS server block. nginx then answers a plain HTTP request on that port with a redirect to the HTTPS URL. A dedicated listen 80 server block that returns 301 is the cleaner solution for the standard ports.
Why does my proxy_pass to an HTTPS backend return this error?
Because proxy_pass uses http:// while the backend port speaks TLS. Use proxy_pass https://backend:443; so nginx opens a TLS connection. The same message can also come from a load balancer or health check configured to send HTTP to the HTTPS port.
What are nginx 494, 495 and 496?
494 is a request header or cookie too large for the configured buffers. 495 is a client certificate verification error and 496 means no required client certificate was presented. Like 497 they are nginx-internal codes that reach the client as 400 Bad Request unless you map them with error_page.
Sources
Related
400 Bad Request
400 Bad Request means the server could not parse your request. Find which layer sent it, fix bad JSON and oversized cookies or headers, and reproduce with curl.
431 Request Header Fields Too Large
The server refuses to process the request because header fields are too large. Learn how to handle and prevent 431 errors in your applications.
ERR_TOO_MANY_REDIRECTS: Find and Break the Redirect Loop
Fix ERR_TOO_MANY_REDIRECTS (redirected you too many times): Cloudflare Flexible SSL, WordPress URLs, nginx HTTPS loops and cookie loops, diagnosed with curl.
HTTP 301 Moved Permanently: Permanent Redirect
Learn what 301 redirect means, when to use it vs 302, and how to implement permanent redirects for SEO and URL changes.