HTTP 408

408 Request Timeout

Client Error

The server did not receive a complete request from the client within the time it was prepared to wait. 408 is a hint to the client that it can retry the request. The issue is with how the request was delivered, not what the request asked for. The response should include Connection: close so the client knows to open a fresh connection on retry. Note this is distinct from 504, which is a timeout against an upstream server, not against the client.

When does this happen?

408 is returned by servers that have configured request-receive timeouts. Long-running form submissions with large file uploads, mobile clients on flaky connections, and clients that opened a persistent connection and then idled past the keep-alive timeout all commonly produce 408. Modern browsers will silently retry 408 once on safe (idempotent) methods, which is why intermittent 408s are sometimes invisible in user-facing logs. The 408 path is also used by some servers as a graceful way to close an idle keep-alive connection. The response is usually small and includes Connection: close. Clients should retry after a short delay; for non-idempotent methods (POST without an idempotency key), retry only if you can ensure no side effects from the original attempt.

Common causes

How to fix it

Real-world examples

User uploading a 200MB video over a 3G connection sees the upload stall at 80%.
Server's client_body_timeout fires and returns 408. Client retries the upload with a resumable protocol that continues from where it left off.
Keep-alive connection idles for 65 seconds and the server's timeout is 60s.
Server returns 408 with Connection: close. Client opens a fresh TCP connection for the next request.
Mobile client briefly loses signal in the middle of a POST body.
Server returns 408 once the client_body_timeout elapses. The mobile SDK retries automatically when the connection comes back.
Browser's autofill plugin delays form submission while it injects values, exceeding the server's idle timeout.
Server returns 408. Browser silently retries the request and the form submits successfully.

How it differs from related codes

HTTP 504

504 is a gateway timeout. The proxy waited for an upstream server too long. 408 is a client-side timeout. The server waited for the client too long. The fixes are on opposite sides of the connection.

HTTP 429

429 means the server received your request but is rate-limiting you. 408 means the server did not receive a complete request in time. Retry strategies are different. Back off for 429, retry quickly for 408.

HTTP 499

499 (a non-standard Nginx code) means the client closed the connection before the server replied. 408 means the server gave up waiting on the client. They are mirror images.

Related status codes

400 429 500 502 503 504

See HTTP 408 in your redirect chains?

Check your URLs with checkredirects.io