408 Request Timeout

A 408 Request Timeout means the server closed the connection because the client took too long to send the full request. It is a client-side HTTP error: the server was ready, but the request headers or body never arrived in time. Because the request was never fully received, nothing on the server got processed, which is why a 408 is usually safe to retry.

Updated June 2026 · 8 min read

  • Written by

    Andrian Valeanu Andrian Valeanu Founder of Pulsetic

    Andrian Valeanu founded Pulsetic and, before it, Designmodo. Across 15-plus years he has shipped web products, design tools, and monitoring software teams around the world rely on.

  • Reviewed by

    Ionut Caval Ionut Caval Technical reviewer

    Ionut Caval reviews Pulsetic's technical guides for accuracy. He works hands-on with web servers, networking, and uptime monitoring day to day, and makes sure the causes and fixes here hold up in production.

The short version: The server timed out while waiting for the client to finish transmitting its request and gave up. It is almost always caused by a slow or dropped client connection, an idle keep-alive socket, or a server timeout set too aggressively.

Key takeaways

  • A 408 means the server gave up waiting for the client to finish sending its request, so the slow side is the request being sent, not the response coming back.
  • It is one of the few 4xx codes safe to retry automatically, because the server never received a complete request and so processed nothing.
  • Many real 408s are harmless: browsers open speculative pre-connect sockets that sit idle, the server times them out, and the browser silently retries on a fresh connection.
  • nginx is the classic surprise: on a header or body timeout it logs 408 but closes the socket without sending any 408 page (ticket 1005), so a log entry does not mean a visitor saw a 408.
  • Fix recurring 408s by aligning read and keep-alive timeouts across every layer rather than chasing zero, since a proxy with a shorter timeout than the backend will close connections first.
Error type
HTTP 4xx client error
Whose side
Either
Fix difficulty
Varies
Common cause
Client too slow sending the full request before the server's read timeout elapsed

What does 408 Request Timeout mean?

The 408 Request Timeout status code means the server did not receive a complete request from the client within the time it was prepared to wait. RFC 9110 (which obsoletes RFC 7231) frames it as the server deciding to shut down a connection because the client did not produce a request in time. The key detail is that this is about the client being slow to send, not the server being slow to respond. The bytes of the request line, headers, or body arrived too slowly, or stopped arriving, so the server abandoned the connection. Per the spec the server should include a Connection: close header to signal it is hanging up rather than waiting longer.

A large share of real-world 408s have nothing to do with an actual page request. Browsers like Chrome and Firefox open speculative TCP and TLS connections ahead of time (pre-connect) to make the next click feel instant. When one of those pre-opened sockets sits idle and is never used, the server's keep-alive or header timeout fires and it logs a 408. The browser almost always retries the navigation silently on a fresh connection, so the user sees nothing. That is why 408 is one of the few 4xx codes considered safe to retry automatically: the server never processed a request, so a retry cannot duplicate any action.

An important nuance for diagnosis: many servers do not actually send the 408 response to the client at all. nginx is the classic example. When client_header_timeout or client_body_timeout elapses, nginx records 408 in its own access log but simply closes the TCP connection without writing any HTTP status line (see nginx ticket 1005). The client, a proxy, or a CDN in front of it just sees an abruptly closed, empty connection and has to infer that a timeout happened. So a 408 in a log does not guarantee any visitor ever received a 408 page.

Because 408 points specifically at the request-sending phase, it isolates a different part of the stack than its neighbours. A 408 says the client side was too slow to finish sending; a 504 Gateway Timeout says an upstream or backend was too slow to respond; a 503 Service Unavailable says the server is up but temporarily unable or unwilling to handle the request. Reading the code correctly tells you which direction to investigate.

YouDNSNetworkCDN / ProxyWeb serverApp / DB
The path a request takes from your browser to the website's servers. A 408 Request Timeout is produced at the highlighted stages.
408
HTTP status code, in the 4xx client error class
RFC 9110
Current spec defining 408 semantics (obsoletes RFC 7231)
60s
Typical default header read timeout on common web servers

How the 408 Request Timeout error appears

The wording changes depending on your browser, device, or server. Here is how this error commonly shows up:

What a 408 Request Timeout looks like in the browser. The exact wording varies by browser, device, and server.
  • 408 Request Timeout The standard RFC reason phrase returned by most servers
  • 408 Request Time-out The hyphenated spelling nginx and some older servers log
  • HTTP Error 408 Generic browser or framework rendering of the status
  • Request Timeout Short form shown on minimal error pages
  • 408 (Request Timeout) Form seen in proxy and load balancer access logs

408 vs related timeouts

Timeout-related status codes often get confused, but each points at a different part of the request lifecycle. Use this table to tell them apart.

Code What it means Where the problem is
408 Request Timeout Server gave up waiting for the client to finish sending the request Client side: slow or stalled request transmission
504 Gateway Timeout A gateway or proxy did not get a timely response from an upstream server Backend or upstream: too slow to respond
503 Service Unavailable Server is up but temporarily unable or unwilling to handle the request Server: overloaded, in maintenance, or rate limiting
499 Client Closed Request Non-standard nginx code: the client closed the connection before the server replied Client side: client gave up and disconnected first
524 A Timeout Occurred Cloudflare-specific: origin connected but did not complete the response in time Origin behind Cloudflare: slow to finish responding

408 vs a connection timeout vs a gateway timeout

These three are easy to confuse because all involve waiting, but each fails at a different moment and points to a different owner.

FailureWhen it happensWhose sideWhat the visitor sees
408 Request TimeoutAfter the connection opens, while the client is still sending request headers or body, and the server's read timeout elapses.Usually the client (slow send) or a too-tight server timeout.A 408 page, a closed connection, or nothing if the browser retries automatically.
Connection timeout (TCP)Before any HTTP request: the TCP handshake never completes because the host is unreachable, down, or firewalled.The server or the network path, not the request itself.ERR_CONNECTION_TIMED_OUT in the browser, or curl: (28) at the command line.
504 Gateway TimeoutAfter a complete request reaches a gateway or proxy, while it waits too long for the upstream backend to respond.The backend or upstream, too slow to reply.A 504 page served by the proxy or CDN.
503 Service UnavailableWhen the server is up but temporarily unable or unwilling to handle the request (overload, maintenance, rate limiting).The server.A 503 page, often with a Retry-After header.

What causes 408 Request Timeout?

  • A slow or unstable client network where request data trickles in or stalls partway, so the headers or body never complete before the server's read timeout.
  • Idle keep-alive or speculative pre-connect sockets (Chrome and Firefox TCP pre-connect) that are opened but never used, so the server times them out and logs 408.
  • Slow or large uploads (big POST or PUT bodies, file uploads on poor connections) that exceed the body read timeout while the body is still in flight.
  • Aggressively low server timeout settings, such as a short nginx client_header_timeout, client_body_timeout, or keepalive_timeout, or a tight Apache RequestReadTimeout.
  • A reverse proxy or load balancer (nginx, HAProxy, AWS ELB) enforcing its own shorter request or keep-alive timeout and closing the connection before the backend would have.
  • Client software or scripts that open a connection, then pause too long before sending the full request, for example a buggy HTTP client or a throttled API caller.

How to find the cause fast

  1. Reproduce with verbose curl and watch the timing breakdown: curl -w 'connect:%{time_connect} starttransfer:%{time_starttransfer} total:%{time_total}\n' -o /dev/null -s https://example.com . A 408 tied to slow request sending shows the connection opening fine but the transfer stalling.
  2. Check the web server access and error logs for 408 entries. On nginx, remember the 408 may appear only in the log while the client just saw a closed connection, so correlate log timestamps with client-side failures.
  3. Inspect the response headers when a 408 is actually returned: curl -sI https://example.com . A genuine 408 response includes a status line of HTTP/1.1 408 Request Timeout and usually a Connection: close header.
  4. Distinguish 408 from 504 by testing whether the failure happens while you are sending (slow upload, large body) versus while you are waiting for a reply (slow backend). 408 fails during send; 504 fails during the wait for an upstream response.
  5. If a proxy or load balancer sits in front, test the origin directly and the proxy endpoint separately to find which layer is closing the connection first, since each layer enforces its own timeout.
What a 408 Request Timeout looks like from the command line. The grey lines starting with # are explanatory comments.

How 408 Request Timeout looks from the outside

From outside, a 408 is inconsistent and easy to miss with the naked eye, because it usually comes from a slow or idle connection rather than a broken page, and many servers (nginx among them) close the socket without ever sending a 408 body. An external monitor like Pulsetic helps by checking your URLs on a fixed schedule, as often as every 30 seconds, from 15+ global locations using real HTTP, TCP, or ICMP requests. If a check gets a 408 status or the connection is closed before a response arrives, Pulsetic records it and can alert you. Because checks run from many regions, you can also tell whether timeouts are global (a server or config issue) or limited to certain networks (a routing or peering problem). Pulsetic measures availability and response from the outside, the way a visitor experiences it; it does not read your server's CPU, memory, or disk.

To confirm the exact code a URL returns, or to re-test several at once after a fix, run them through the free bulk URL status checker.

How to fix 408 Request Timeout

For visitors

  1. Reload the page. Many 408s come from a stale idle connection and the retry succeeds immediately on a fresh one.
  2. Check your internet connection. A slow, congested, or dropping network is the most common cause of the request not finishing in time; switch from weak Wi-Fi to a wired or stronger connection if you can.
  3. If you were uploading a large file or submitting a big form, try again on a faster, more stable connection, since slow uploads can exceed the server's body timeout.
  4. Disable a VPN or proxy temporarily to rule out an intermediary that is slowing or interrupting the request.
  5. Clear the browser cache and any stale cookies, then retry, in case a malformed or oversized request was being sent.

For website owners

  1. Review your web server read timeouts and raise them if they are too aggressive. On nginx tune client_header_timeout, client_body_timeout, and keepalive_timeout; on Apache tune RequestReadTimeout in mod_reqtimeout.
  2. Make sure keep-alive timeouts are aligned across every layer. If a proxy or load balancer has a shorter timeout than the backend, the proxy will close connections first and generate 408s.
  3. For endpoints that accept large uploads, set a body timeout generous enough for slow clients to finish, and consider chunked or resumable uploads rather than a single large request.
  4. Expect and tolerate harmless 408s from browser pre-connect sockets; they are normal and browsers retry automatically, so do not over-tighten timeouts trying to eliminate them entirely.
  5. If 408s are spiking, check whether a misconfigured CDN, load balancer, or firewall in front of your origin is holding connections open or closing them early.
  6. Monitor the public availability of the affected URLs from outside your network so you can tell a real outage from background pre-connect noise.

Still not fixed? Next steps

  • Time each phase with curl -o /dev/null -s -w 'connect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n' https://example.com: a 408 shows the connection opening fine but the transfer stalling, which separates it from a connection timeout (28).
  • On nginx, raise client_header_timeout, client_body_timeout, and keepalive_timeout if they are too aggressive, and remember to correlate log 408s with real client failures since nginx may only log them.
  • On Apache, tune RequestReadTimeout in mod_reqtimeout so slow clients on poor networks can finish sending, especially on endpoints that accept large uploads.
  • If a proxy, load balancer, or CDN sits in front of the origin, test the origin directly and the proxy endpoint separately to find which layer enforces the shortest timeout and closes the connection first.

Code & configuration

Copy-paste starting points. Replace example.com and the paths with your own, and test changes on staging before production.

nginx: request read and keep-alive timeouts

http {
    # Time to read the full request header from the client
    client_header_timeout 60s;

    # Time between successive reads of the request body
    client_body_timeout   60s;

    # How long an idle keep-alive connection stays open
    keepalive_timeout     75s;
}
# Note: on timeout nginx logs 408 but closes the connection
# without sending a 408 response to the client (ticket 1005).

Apache: RequestReadTimeout (mod_reqtimeout)

# Load the module, then set header and body read timeouts.
LoadModule reqtimeout_module modules/mod_reqtimeout.so

# header: wait up to 20s, then extend to 40s max as data arrives
# body:   wait up to 20s, then require at least 500 bytes/sec
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
# If a stage is not completed in time, Apache sends 408.

curl: confirm a 408 and time the request

# See the status line and any Connection: close header
curl -sI https://example.com

# Time each phase to spot a stalled request send
curl -o /dev/null -s \
  -w 'connect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n' \
  https://example.com

How to prevent 408 Request Timeout

Most 408s are prevented by aligning timeouts sensibly across every layer rather than chasing zero. Set web server read timeouts (nginx client_header_timeout and client_body_timeout, Apache RequestReadTimeout) generously enough for real clients on slow networks, keep keep-alive timeouts consistent between your proxy or load balancer and your backend, and offer resumable uploads for large request bodies. Then accept that a trickle of harmless 408s from browser pre-connect sockets is normal. To catch the 408s that actually matter, monitor your endpoints continuously from outside with a service like Pulsetic, which checks availability from multiple locations on a short interval and alerts you by email, SMS, voice call, Slack, Discord, Telegram, or webhook the moment requests start timing out, so a configuration regression does not go unnoticed.

Learn how Pulsetic's uptime monitoring detects this from the outside, across 15+ locations.

Frequently asked questions

  • Is a 408 error my fault or the website's fault?

    It can be either. A 408 means the request did not finish arriving in time. That is often caused by a slow or dropped connection on the visitor's side, but it can also be caused by server timeouts set too aggressively or a proxy closing connections early, which is the website owner's responsibility. Start by reloading and checking your connection; if it persists across networks and devices, the server configuration is the likely culprit.

  • What is the difference between a 408 and a 504 error?

    A 408 means the server gave up waiting for the client to finish sending its request, so the problem is on the sending side. A 504 Gateway Timeout means a gateway or proxy did not get a timely response from an upstream server, so the problem is the backend being too slow to respond. 408 fails while the request is being sent; 504 fails while the client is waiting for a reply.

  • Why do I see 408 errors in my nginx logs but visitors do not report them?

    nginx records 408 in its access log when a client header or body timeout elapses, but it typically closes the TCP connection without sending an actual 408 response (documented in nginx ticket 1005). On top of that, many of these come from browser pre-connect sockets that are opened speculatively and never used, and browsers retry automatically. So the log entries are usually harmless background noise rather than visible failures.

  • Is it safe to retry a request that returned 408?

    Generally yes. Because a 408 means the server never received the complete request, it did not process anything, so retrying will not cause a duplicate action. This is why 408 is one of the few 4xx codes commonly retried automatically by browsers and HTTP clients, ideally with a short backoff.

  • How do I fix repeated 408 errors on my own server?

    Review your read timeouts and raise them if they are too low: on nginx adjust client_header_timeout, client_body_timeout, and keepalive_timeout; on Apache adjust RequestReadTimeout in mod_reqtimeout. Make sure any proxy or load balancer in front uses timeouts at least as long as the backend, so it does not close connections early. For large uploads, allow a longer body timeout or use resumable uploads.

  • Can monitoring tell me when 408 timeouts are happening?

    Yes. An external monitor such as Pulsetic checks your URLs on a short interval from multiple global locations and records when a check returns a 408 or the connection is closed without a response. It can alert you through channels like email, SMS, voice, Slack, Discord, Telegram, or webhook, and comparing results across regions helps you tell a global server issue from a localized network problem. It measures from the outside and does not track server CPU, memory, or disk.

  • What is the difference between a 408 and a connection timeout?

    A connection timeout happens before any HTTP request is sent: the TCP handshake never completes because the host is down, unreachable, or blocked by a firewall, and the browser shows ERR_CONNECTION_TIMED_OUT (curl exit code 28). A 408 happens after the connection is already open: the server accepted the socket but the client was too slow to finish sending the request, so the server closed it. In short, a connection timeout means you never reached the server, while a 408 means you reached it but did not finish talking in time.

  • What are browser pre-connect sockets and why do they cause 408s?

    To make the next click feel instant, Chrome and Firefox speculatively open TCP and TLS connections to websites you might visit before you actually request a page. If one of those pre-opened sockets is never used, it sits idle until the server's keep-alive or header read timeout fires, and the server logs a 408. The browser simply opens a fresh connection when you do navigate, so you never see an error. This is why a steady trickle of 408s in your logs is normal background noise rather than a real failure.

  • Does a 408 count as downtime?

    Usually not. A 408 means the server was up and accepting connections; it just gave up on one slow or idle request, and most are harmless pre-connect sockets that browsers retry automatically. It only signals a real problem when 408s spike across many visitors and networks, which points to timeouts set too aggressively or a proxy closing connections early. Monitoring from multiple outside locations helps you tell a genuine, widespread issue from normal background noise.

  • Why does Apache return a 408 page but nginx does not?

    They handle the timeout differently. Apache's mod_reqtimeout sends an actual 408 Request Timeout response when a read stage is not completed in time. nginx, by contrast, records 408 in its access log when client_header_timeout or client_body_timeout elapses but typically just closes the TCP connection without writing any HTTP status line (documented in nginx ticket 1005). So whether a visitor ever sees a 408 page depends on which server, proxy, or CDN is terminating the connection.

  • What timeout value should I set to avoid false 408s?

    There is no single right number, but the goal is to be generous enough for real clients on slow networks without holding dead connections open forever. Defaults around 60 seconds for header and body reads and roughly 75 seconds for keep-alive are reasonable starting points on nginx, with similar values for Apache's RequestReadTimeout. The more important rule is consistency: make sure any proxy or load balancer in front uses timeouts at least as long as the backend, otherwise the front layer closes connections first and generates 408s no matter how the backend is tuned.