# 444 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.

Source: https://howhttpworks.com/status-codes/444
Last reviewed: 2026-10-04

> **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" or `ERR_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:

```text
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](https://howhttpworks.com/status-codes/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:

```nginx
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:

```nginx
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

```bash
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 = /healthz` returning 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](https://howhttpworks.com/status-codes/502) or Cloudflare's [520](https://howhttpworks.com/status-codes/520). If legitimate traffic is being dropped by accident, that CDN error is how you will find out.
- **Not a rate limiter.** `limit_req` and `limit_conn` return 503 by default (change it with `limit_req_status 429`). Use [429](https://howhttpworks.com/status-codes/429) when you want well-behaved clients to slow down.

## Related

- [499 Client Closed Request](https://howhttpworks.com/status-codes/499): the other nginx log-only code, where the client closed first.
- [403 Forbidden](https://howhttpworks.com/status-codes/403): an explicit refusal with a response.
- [429 Too Many Requests](https://howhttpworks.com/status-codes/429): the polite way to throttle.
- [502 Bad Gateway](https://howhttpworks.com/status-codes/502)
- [ERR_EMPTY_RESPONSE](https://howhttpworks.com/debug/err-empty-response): what a browser shows for a 444, and how to tell it apart from a crash or a wrong port.
