No Response
ActiveHTTP 444 No Response is a non-standard nginx status code. nginx closes the TCP connection without sending any response headers or body. The client sees a connection reset, never an HTTP status. Used via 'return 444;' in nginx config to silently drop malicious requests, bots, or unwanted traffic without revealing server existence.
Description
The 444 No Response status code is an nginx-specific, non-standard extension that does not appear in any RFC or IANA registry. When nginx encounters a `return 444;` directive, it immediately closes the TCP connection without transmitting a single byte of HTTP response — no status line, no headers, no body. The client experiences a connection reset or unexpected close, indistinguishable from a network failure.
This behavior makes 444 fundamentally different from every other HTTP status code. Standard error codes like 403 or 503 still send a complete HTTP response that confirms a server exists and is processing requests. With 444, the server becomes a black hole — the request goes in, nothing comes out. From the client's perspective, it is as if no server is listening on that port at all.
The primary use case is security: blocking malicious requests, mitigating bot traffic, dropping connections from banned IPs or suspicious User-Agents, and hiding server existence from scanners. Because no response bytes are generated, 444 is more efficient than returning a proper error — it saves bandwidth, CPU cycles, and avoids leaking any server fingerprint information.
In nginx's access.log, these requests are recorded with status 444 for operational visibility, but the client never sees this number. It is purely an internal nginx concept — a directive that means 'terminate this connection silently.' The distinction matters: 444 is an intentional server directive, not a network accident. The nginx process actively decides to drop the connection based on configuration rules.
Common deployment patterns include blocking by IP range, rejecting requests with missing or suspicious Host headers, dropping traffic to undefined virtual hosts, filtering by User-Agent string, and protecting sensitive paths from enumeration. It is frequently combined with nginx's `if`, `map`, and `geo` directives for flexible traffic filtering.
Examples
server {
listen 80 default_server;
server_name "";
return 444;
}geo $blocked {
default 0;
10.0.0.0/8 1;
192.168.1.0/24 1;
203.0.113.50 1;
}
server {
listen 80;
server_name api.example.com;
if ($blocked) {
return 444;
}
location / {
proxy_pass http://backend;
}
}map $http_user_agent $bad_bot {
default 0;
~*sqlmap 1;
~*nikto 1;
~*dirbuster 1;
~*nmap 1;
~*masscan 1;
"" 1;
}
server {
listen 443 ssl;
server_name secure.example.com;
if ($bad_bot) {
return 444;
}
location / {
proxy_pass http://app;
}
}server {
listen 80;
server_name example.com;
location ~ /\.(git|env|htaccess|svn) {
return 444;
}
location ~* /(wp-admin|wp-login|phpmyadmin|admin\.php) {
return 444;
}
location / {
proxy_pass http://backend;
}
}$ curl -v http://example.com/secret-path
* Trying 93.184.216.34:80...
* Connected to example.com (93.184.216.34) port 80
> GET /secret-path HTTP/1.1
> Host: example.com
> User-Agent: curl/8.4.0
> Accept: */*
>
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server203.0.113.50 - - [15/Jan/2024:10:28:33 +0000] "GET /.env HTTP/1.1" 444 0 "-" "python-requests/2.31.0"
203.0.113.51 - - [15/Jan/2024:10:28:34 +0000] "POST /wp-login.php HTTP/1.1" 444 0 "-" "Mozilla/5.0"
10.0.0.5 - - [15/Jan/2024:10:28:35 +0000] "GET /admin HTTP/1.1" 444 0 "-" "sqlmap/1.7"Edge Cases
- •The client NEVER receives status code 444 — it only appears in nginx's access.log. The client sees a connection reset (ECONNRESET) or empty reply, indistinguishable from a network failure.
- •444 is NOT a valid HTTP status code per any RFC. Sending '444 No Response' as an actual HTTP response defeats its purpose — the point is that NO response is sent at all.
- •Load balancers and CDNs in front of nginx may interpret the connection drop differently — some retry the request on another backend, some return their own 502/503 to the client.
- •Monitoring tools that track HTTP status codes may miscount 444 responses. The connection closes before any status is transmitted, so client-side monitoring sees a network error, not an HTTP error.
- •Using 444 for legitimate clients (misconfigured blocking rules) causes silent failures that are extremely difficult to debug — there is no error message, no response body, no hint of what went wrong.
- •Rate limiting with 444 (instead of 429) provides no feedback to legitimate clients that they are being throttled. Use 444 only when you WANT no feedback — when the client is adversarial.
- •In HTTP/2 and HTTP/3, the connection semantics differ. nginx still drops the stream, but multiplexed connections mean other streams on the same connection may be affected depending on implementation.
When You'll See This
- →Silently dropping connections from known-malicious IP ranges without revealing server existence
- →Blocking vulnerability scanners (sqlmap, nikto, dirbuster) by User-Agent without confirming the server is alive
- →Catching requests to the default server block when no matching virtual host exists
- →Dropping requests with missing, empty, or mismatched Host headers (common in automated scanning)
- →Protecting sensitive files (.env, .git, wp-config.php) from enumeration attempts
- →Filtering unwanted health check probes from services you do not control
- →Rate-limiting aggressive crawlers beyond what robots.txt allows — without telling them they are blocked
Implementation References
| Language | Constant |
|---|---|
| nginx | return 444; |
| nginx (map) | map $variable $action { default 0; pattern 444; } |
| OpenResty/Lua | ngx.exit(444) |
| Go (nginx-equivalent) | conn.Close() // no http.ResponseWriter write |
| Node.js (raw socket) | req.socket.destroy() // no response sent |
| Python (equivalent) | # Close socket without response — not native HTTP |
| HAProxy (equivalent) | http-request silent-drop |
| Caddy (equivalent) | abort // Caddy's equivalent of nginx 444 |
History
Introduced in nginx circa 2004 by Igor Sysoev as an internal mechanism for silently dropping connections. Unlike standard HTTP status codes that go through IETF standardization and IANA registration, 444 was created as a pragmatic server implementation detail. It filled a gap that no standard status code addressed: the ability to close a connection without any HTTP-level response. Over time, it became one of nginx's most distinctive features and a standard tool in web security configurations. Other web servers have not adopted 444 — it remains exclusively an nginx concept. Its effectiveness comes from the fact that no response leaks server existence, software version, or behavioral patterns to attackers. The nginx documentation lists it under the rewrite module's `return` directive, positioned as a special case rather than a standard HTTP status.
Related Status Codes
Related Headers
FAQ
What does the client actually see when nginx returns 444?
The client never receives an HTTP response. nginx closes the TCP connection immediately without writing any bytes to the socket. The client's HTTP library sees a connection reset (ECONNRESET) or an empty reply — the exact error depends on timing and OS. curl reports 'Empty reply from server' (error 52). Browsers show ERR_EMPTY_RESPONSE or ERR_CONNECTION_RESET. From the client's perspective, it is indistinguishable from a network failure or a server that is not listening. The status code 444 only exists in nginx's access.log for the server operator's benefit.
Why use 444 instead of 403 Forbidden to block unwanted requests?
A 403 response confirms three things to an attacker: (1) a server exists at this address, (2) the server is running and processing requests, and (3) the server recognized the request as forbidden — meaning the path or resource likely exists but is protected. With 444, the attacker learns nothing. No server fingerprint, no software version in headers, no confirmation the server exists. Additionally, 444 is more efficient: generating a proper 403 response requires constructing headers, potentially rendering an error page, and transmitting bytes. With 444, nginx simply closes the file descriptor — zero response bytes, minimal CPU, minimal bandwidth. For high-volume bot traffic, this efficiency difference matters.
Can I use 444 outside of nginx? Is it supported by other web servers?
No. 444 is exclusively an nginx internal directive, not a real HTTP status code. Other web servers do not recognize it. However, most servers have equivalent mechanisms: Caddy has `abort` which drops the connection without response, HAProxy has `http-request silent-drop`, Apache can achieve similar behavior with mod_security's `drop` action, and at the application level you can close the raw TCP socket without writing any HTTP response. The conceptual operation — close connection without response — is universal, but the specific '444' code is nginx-only. If you put 444 in an HTTP response from a non-nginx server, it would be sent as an actual HTTP status line to the client, which defeats the entire purpose.