{"record":{"id":"e99c4e2a8a97f1ab","repo":"nginx/nginx","slug":"400-the-plain-http-request-was-sent-to-https-port","errorCode":null,"errorMessage":"400 The plain HTTP request was sent to HTTPS port","messagePattern":"400 The plain HTTP request was sent to HTTPS port","errorType":"http","errorClass":null,"httpStatus":497,"severity":"error","filePath":"src/http/ngx_http_special_response.c","lineNumber":282,"sourceCode":"\"<head><title>400 The SSL certificate error</title></head>\"\nCRLF\n\"<body>\" CRLF\n\"<center><h1>400 Bad Request</h1></center>\" CRLF\n\"<center>The SSL certificate error</center>\" CRLF\n;\n\n\nstatic char ngx_http_error_496_page[] =\n\"<html>\" CRLF\n\"<head><title>400 No required SSL certificate was sent</title></head>\"\nCRLF\n\"<body>\" CRLF\n\"<center><h1>400 Bad Request</h1></center>\" CRLF\n\"<center>No required SSL certificate was sent</center>\" CRLF\n;\n\n\nstatic char ngx_http_error_497_page[] =\n\"<html>\" CRLF\n\"<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>\"\nCRLF\n\"<body>\" CRLF\n\"<center><h1>400 Bad Request</h1></center>\" CRLF\n\"<center>The plain HTTP request was sent to HTTPS port</center>\" CRLF\n;\n\n\nstatic char ngx_http_error_500_page[] =\n\"<html>\" CRLF\n\"<head><title>500 Internal Server Error</title></head>\" CRLF\n\"<body>\" CRLF\n\"<center><h1>500 Internal Server Error</h1></center>\" CRLF\n;\n\n\nstatic char ngx_http_error_501_page[] =","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/nginx/nginx/blob/3f6f7824d4e2eb1ac37dec76683d525ac0ff521c/src/http/ngx_http_special_response.c#L264-L300","documentation":"This is nginx's built-in error page for pseudo-status 497 (NGX_HTTP_TO_HTTPS, defined in src/http/ngx_http_request.h), served to the client with status 400. When a listener has 'ssl' enabled, nginx expects a TLS handshake; if the first bytes parse as a plain HTTP request line instead, nginx logs \"client sent plain HTTP request to HTTPS port\" (src/http/ngx_http_request.c:2142) and sends this page from the ngx_http_error_pages[] table in ngx_http_special_response.c. It means the client used the wrong scheme for that port.","triggerScenarios":"Running 'curl http://example.com:443/' against a 'listen 443 ssl;' server; a health checker or uptime monitor configured with http:// against the TLS port; a load balancer whose backend protocol is HTTP while the target expects TLS; an internal proxy_pass that omits 'https://' so nginx speaks plain HTTP to a TLS upstream.","commonSituations":"Container port remapping that maps container 443 to host 8080 and clients then try http://host:8080; AWS ELB/ALB target-group protocol mismatch; scripts where the scheme is built from config and defaults to http; migration from port 80 to 443 without updating monitoring probes.","solutions":["Change the client to use https:// against the TLS port (or http:// against a plain port).","If you want an automatic upgrade, add 'error_page 497 =301 https://$host$request_uri;' to the ssl server block.","Split listeners: one 'listen 80;' server that redirects and one 'listen 443 ssl;' server for TLS traffic.","For proxy hops, fix the upstream scheme: 'proxy_pass https://backend;' or set the load balancer backend protocol to HTTPS/TLS."],"exampleFix":"// before\nserver {\n    listen 443 ssl;\n    server_name example.com;\n}\n// client: curl http://example.com:443/  -> 400 The plain HTTP request was sent to HTTPS port\n\n// after\nserver {\n    listen 80;\n    server_name example.com;\n    return 301 https://$host$request_uri;\n}\nserver {\n    listen 443 ssl;\n    server_name example.com;\n    error_page 497 =301 https://$host$request_uri;\n}","handlingStrategy":"validation","validationCode":"# before connecting, verify the scheme/port pairing actually served\nscheme=443_tls_only\ncurl -sI \"http://$host:$port/\" | head -n1   # if this prints '400 ... HTTPS port', use https\ncurl -sI \"https://$host:$port/\" | head -n1  # this must succeed","typeGuard":null,"tryCatchPattern":"try:\n    r = requests.get(f\"https://{host}:{port}/\", timeout=10)\nexcept requests.exceptions.SSLError:\n    # port is NOT speaking TLS even though we assumed https\n    raise","preventionTips":["Keep a single source of truth mapping host:port -> scheme; never guess.","Configure health checks with the exact scheme of the listener.","Add 'error_page 497 =301 https://$host$request_uri;' so wrong-scheme requests self-heal.","In CI, assert that https:// probes succeed on every TLS endpoint before shipping config."],"tags":["nginx","https","ssl","wrong-scheme","listen-port","misconfiguration"],"backgroundTag":"http-request-sent-to-https-port","analyzedSha":"3f6f7824d4e2eb1ac37dec76683d525ac0ff521c","analyzedAt":"2026-08-22T03:09:46.447Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}