Skip to content
Webmaster Tools
Inspect & debugHTTP Status Codes499 Client Closed Request

499 Client Closed Request

What the nginx 499 Client Closed Request status means, why it shows up only in access logs, the timeouts and slow backends behind it, and how to track them down.

All status codes

What 499 means

499 is not a standard HTTP status code. It's nginx's own code (NGX_HTTP_CLIENT_CLOSED_REQUEST) for one situation: the client closed the connection while nginx was still waiting to send the response. Nobody receives a 499, since the client has already gone; nginx only writes it to the access log:

203.0.113.7 - - [05/Oct/2026:10:14:02 +0000] "GET /report HTTP/1.1" 499 0 "-" "Mozilla/5.0 ..."

The 0 bytes sent is typical. Other servers record the same event differently, and a few products use 499 for unrelated things, but in a web server log it nearly always means nginx.

Common causes

  • Users giving up: closing the tab, navigating away, or pressing reload while a slow page loads.
  • Cancelled requests in the page: AbortController, search-as-you-type that cancels the previous request, or a single-page app changing route.
  • Client timeouts shorter than the backend: a mobile app that waits 10 seconds for an endpoint that takes 15, or a load balancer in front of nginx whose idle timeout runs out first. The user then sees an error from that client or load balancer (often a 504), while nginx logs 499.
  • Health checks and monitors with short timeouts hitting a slow endpoint.
  • A slow upstream: database locks, cold starts or an overloaded app, which makes every other cause above more likely.

A few 499s are normal on any busy site. A spike on one endpoint means it's too slow.

How to fix it

Find what's slow. Log the request and upstream times, then sort the 499 lines by them:

log_format timing '$remote_addr "$request" $status '
                  'rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log timing;

If urt is close to some fixed number (10 s, 30 s, 60 s), a timeout in a client or load balancer is cutting the request off.

Line up the timeouts. Each layer should wait a little longer than the one behind it: client, then load balancer, then nginx (proxy_read_timeout, 60 s by default), then the app. Better still, make the endpoint fast: add caching or indexes, or move long work to a background job and return 202 with a status URL.

Let important work finish. By default nginx closes the upstream connection when the client leaves, which can abort the app's work halfway. For endpoints that must complete (payments, webhooks), set:

location /webhooks/ {
    proxy_ignore_client_abort on;
    proxy_pass http://app;
}

Make those handlers idempotent too, since the client will probably retry.

499 and SEO

Google never sees a 499. If Googlebot gives up on a slow page, nginx logs 499 and Google records a timeout or server error, and slows its crawl rate if that keeps happening. So 499 lines with a Googlebot user agent are a sign of pages that answer too slowly. Speed them up rather than raising timeouts.

To time how long a URL takes to answer, request it with the HTTP Request Builder.