What 408 means
The server didn't receive a complete request within the time it was prepared to wait, so it gave up and is closing the connection. 408 is defined in RFC 9110 §15.5.9. The problem is the time spent sending the request, not the time the server takes to answer: a slow backend gives 504 Gateway Timeout instead.
HTTP/1.1 408 Request Timeout
Connection: close
Content-Type: text/html
<h1>Request Timeout</h1>
The server should send Connection: close, and the client can repeat the request on a new connection. Browsers do this by themselves when a 408 arrives on a reused keep-alive connection.
Common causes
- Idle connections. A browser opens a connection speculatively (preconnect) and never sends a request; Apache logs these as 408 with an empty request line. They're harmless.
- Slow or unstable clients: mobile networks dropping packets mid-upload, or a large body sent over a slow link.
- Short server timeouts for uploads, set lower than a real user needs to send a large file.
- Load balancers: AWS Application Load Balancer answers 408 when the client sends nothing before the idle timeout.
- Slowloris-style attacks that open connections and trickle headers on purpose; the timeout is the defence.
How to fix it as a client
Retry once on a fresh connection; it's safe for GET and other idempotent requests. If it keeps happening on uploads, check the network, compress the body, or switch to a chunked or resumable upload.
How to fix it on the server
Raise the timeout only where real clients need it, such as an upload endpoint, and keep it short elsewhere. In nginx both default to 60 seconds:
location /upload {
client_header_timeout 60s;
client_body_timeout 300s;
}
client_body_timeout is the gap allowed between two reads, not the whole upload. In Apache, mod_reqtimeout sets the limits, with a minimum data rate that extends them while data keeps arriving:
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
In Node.js, server.headersTimeout (60 s) and server.requestTimeout (300 s since Node 18) control when the server answers 408.
If the 408s in your logs have no request line, they're idle preconnects and need no fix.
408 and SEO
A real 408 means Googlebot couldn't even send its request in time, which is rare. Google treats every 4xx except 429 as "the content doesn't exist", so a URL that keeps answering 408 can drop from the index. If a CDN or firewall answers Googlebot with 408, fix the rule instead of waiting.
Related codes
- 504 Gateway Timeout: the upstream was too slow to answer, not the client too slow to ask.
- 499 Client Closed Request: the reverse, where the client gave up waiting for nginx.
- 429 Too Many Requests: the right code for slowing a client down.
- 413 Content Too Large: the body was too big rather than too slow.
To check what a URL answers and how long it takes, use the HTTP Request Builder or the Redirect Checker.