< HTTP/1.1 444 No Response444 Connection Closed Without Response (nginx)
nginx 444 closes the connection without sending any response. Learn how to use return 444 to drop bots and unknown hosts, and what clients see.
- Cacheable
- No
- Retry?
- No response was sent; the connection was closed
- Usually sent by
- nginx (return 444)
TL;DR:
return 444;makes nginx close the TCP connection without sending any response. It is a cheap way to drop scanners and requests for hostnames you do not serve, and the client sees “Empty reply from server” orERR_EMPTY_RESPONSE.
What it means
444 is not a status code anyone receives. It is a signal inside nginx’s return directive meaning “close the connection, say nothing”. Because no response is written, there is no status line, no headers and no body. Access logs record 444 with a body size of 0:
198.51.100.23 - - [04/Oct/2026:03:12:09 +0000] "GET /wp-login.php HTTP/1.1" 444 0 "-" "python-requests/2.32.3"
Compared to 403, the scanner learns less (no Server header, no error page) and nginx does slightly less work. Compared to letting the request time out, the socket is freed immediately.
Common uses
Drop requests for hostnames you do not serve. nginx picks a server block by Host; if nothing matches it uses the default_server. Make that block refuse everything:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
# Refuse the TLS handshake for unknown SNI (nginx 1.19.4+).
# No certificate is needed in this block.
ssl_reject_handshake on;
}
Without ssl_reject_handshake, the HTTPS default server must present some certificate, which discloses a real hostname to anyone connecting by IP. With it, the handshake fails with an unrecognized_name alert instead.
Drop obviously hostile requests:
map $http_user_agent $block_ua {
default 0;
~*(sqlmap|nikto|masscan) 1;
}
server {
# ...
if ($block_ua) { return 444; }
}
if containing only a return is one of the safe uses of that directive.
What the client sees
curl -i https://example.com/ -H 'Host: unknown.example.net'
# curl: (52) Empty reply from server
Chrome shows ERR_EMPTY_RESPONSE (“didn’t send any data”), Firefox shows “The connection was reset”, and Node’s fetch throws TypeError: fetch failed with a socket-closed cause.
Gotchas
- Health checks. A load balancer that probes by IP with no matching Host header hits your default server and gets nothing back. Point probes at a real server block, or add an explicit
location = /healthzreturning 200 in the default server. - Monitoring blind spot. Clients and CDNs that get an empty reply treat it as a connection failure, not an HTTP error. A CDN in front will typically report 502 or Cloudflare’s 520. If legitimate traffic is being dropped by accident, that CDN error is how you will find out.
- Not a rate limiter.
limit_reqandlimit_connreturn 503 by default (change it withlimit_req_status 429). Use 429 when you want well-behaved clients to slow down.
Related
- 499 Client Closed Request: the other nginx log-only code, where the client closed first.
- 403 Forbidden: an explicit refusal with a response.
- 429 Too Many Requests: the polite way to throttle.
- 502 Bad Gateway
- ERR_EMPTY_RESPONSE: what a browser shows for a 444, and how to tell it apart from a crash or a wrong port.
Frequently asked questions
What does nginx 444 mean?
It is a special value for the return directive that tells nginx to close the connection immediately without sending any HTTP response. The 444 only appears in the access log; the client sees an empty reply or a connection reset.
Why does my browser show ERR_EMPTY_RESPONSE?
Chrome shows ERR_EMPTY_RESPONSE when the server closes the connection without sending a status line. If the server is nginx, a `return 444` rule is a likely cause. curl reports the same condition as "curl: (52) Empty reply from server".
How do I block requests for unknown hostnames with nginx?
Define a default_server block that returns 444, so requests whose Host header matches no real site are dropped. For HTTPS add ssl_reject_handshake on to refuse the TLS handshake for unknown SNI names before any certificate is presented.
Is 444 an official HTTP status code?
No. It is not registered with IANA and appears in no RFC. It is an nginx-internal code that exists only so the access log can say what happened.
Sources
Related
497 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.
499 Client Closed Request (nginx)
nginx 499 means the client hung up before the response was sent. Why it spikes with slow upstreams, how proxy_ignore_client_abort works, and how to debug it.
419 Page Expired (Laravel CSRF Token Mismatch)
Laravel 419 Page Expired means the CSRF token did not match the session. Causes: expired session, missing @csrf, dropped cookie, cached forms. Fixes included.
425 Too Early: TLS 1.3 0-RTT Replay Protection
425 Too Early tells a client not to send a request in TLS early data because it could be replayed. See the Early-Data header and nginx config for 0-RTT.