# HTTP 408 Request Timeout — Meaning, Causes & Fixes

> The server gave up waiting for the client to finish sending the request.

408 means the client was too slow, not the server. The connection opened, but the full request didn't arrive within the server's timeout. Servers also send 408 when closing idle keep-alive connections. Because the request never fully arrived, it's safe to retry.

- Class: 4xx Client Error
- Retry: Yes — safe to retry
- Cacheable by default: no
- Defined in: [RFC 9110 §15.5.9 — 408 Request Timeout](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.9)

## Example response

```http
HTTP/1.1 408 Request Timeout
Content-Type: application/json
Content-Length: 27

{"error":"Request Timeout"}
```

## Common causes

- Slow or flaky networks — mobile data, overloaded Wi-Fi.
- Large uploads over slow links exceeding the server's body timeout.
- Idle keep-alive connections being closed (browsers retry these automatically).

## How to fix it

1. Retry the request — the spec expects clients to.
2. For large uploads, use chunked or resumable uploads.
3. On the server, raise `client_body_timeout` (nginx) or its equivalent if legitimate clients hit it.

## Send a 408 from your server

### Express

```
res.status(408).json({ error: "Request Timeout" });
```

### Next.js route handler

```
return Response.json({ error: "Request Timeout" }, { status: 408 });
```

### Flask

```
return {"error": "Request Timeout"}, 408
```

### Go net/http

```
http.Error(w, "Request Timeout", http.StatusRequestTimeout)
```

### nginx

```
return 408;
```

## FAQ

### 408 vs 504?

408: the server timed out waiting for the client. 504: a gateway timed out waiting for the upstream server. One is a slow client; the other is a slow backend.

## Related status codes

- [504 Gateway Timeout](https://www.devkult.com/http/504.md)
- [499 Client Closed Request](https://www.devkult.com/http/499.md)
- [413 Content Too Large](https://www.devkult.com/http/413.md)

Open the interactive page: https://www.devkult.com/http/408