# 524 A Timeout Occurred

> Cloudflare-specific error when the origin server takes too long to respond. Learn how to diagnose and fix 524 timeout errors.

Source: https://howhttpworks.com/status-codes/524
Last reviewed: 2026-10-05

> **TL;DR:** HTTP 524 means Cloudflare connected to your server but timed out waiting for it. Check origin request timings, move long jobs to a queue with polling, or raise the read timeout on Enterprise; the default is 125 seconds. A stalled upload to the origin can also hit the separate 30-second write timeout.

## What it means

524 is a Cloudflare extension, not a named status in RFC 9110. Clients handle an unfamiliar 5xx as a server error under [RFC 9110 status extensibility](https://www.rfc-editor.org/rfc/rfc9110.html#section-15).

For a read timeout, Cloudflare established the origin connection but did not receive a timely HTTP response. Cloudflare closes the connection and returns 524 to the visitor. The page says "A timeout occurred". Enterprise customers can raise the proxy read timeout up to 6,000 seconds through the zone settings API, or a Cache Rule for cacheable requests; on other plans it is fixed. A separate 30-second proxy write timeout, which cannot be changed, also produces 524 when writing to the origin stalls. Cloudflare Images uses a 6.5-second write timeout. [Cloudflare 524 documentation](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/).

Use Cloudflare's read/write limits to identify the stalled phase. A handler that waits for a large query before responding can reach the read limit. Treat streaming as a separate endpoint to test through the full proxy chain; merely sending headers early is an incomplete fix. [Connection limits](https://developers.cloudflare.com/fundamentals/reference/connection-limits/).

## What you see in your client

Client messages and the command outcomes below are illustrative. For 524, reason text varies with the response and protocol; use the numeric status for diagnosis.

- **Axios:** `AxiosError: Request failed with status code 524`. Its default status check rejects 524; inspect `error.response.status` and headers. [Axios source](https://github.com/axios/axios/blob/v1.x/lib/core/settle.js).
- **fetch:** resolves with `response.status === 524` and `response.ok === false`. Check `ok` before decoding the body as JSON. [Fetch behaviour](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch).
- **Python requests:** `raise_for_status()` builds `requests.exceptions.HTTPError: 524 Server Error: <Reason> for url: https://example.com/api`. `<Reason>` is `response.reason`, not fixed Cloudflare text. [Requests source](https://github.com/psf/requests/blob/main/src/requests/models.py).
- **curl -f:** `curl: (22) The requested URL returned error: 524`. Capture headers and body with `curl -sS -D - https://example.com/api` while investigating. [curl source](https://github.com/curl/curl/blob/master/lib/http.c).
- **.NET:** with no reason phrase, `EnsureSuccessStatusCode()` throws `System.Net.Http.HttpRequestException: Response status code does not indicate success: 524.` With a phrase, it uses `524 (<Reason>).` in the message. [Runtime source](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs), [message resource](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/Resources/Strings.resx).
- **Spring WebClient:** the generic `WebClientResponseException` carries 524; there is no dedicated 524 subclass. Its message template is `524 <Reason> from GET https://example.com/api`. Save `getStatusCode().value()`, headers and `getResponseBodyAsString()`. [Spring source](https://github.com/spring-projects/spring-framework/blob/main/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java).

If an API wrapper logs `status_code=524` with no body, preserve the URL, timestamp, elapsed time and `CF-Ray`. Inspect the HTTP status before attempting JSON parsing; an HTML error page or empty body gives the parser nothing useful to decode. For a state-changing request, check the job or resource state before retrying because the origin may still be working.

## Who sent it?

Inspect the status together with `server: cloudflare` and `cf-ray`. A read-timeout 524 is near the configured read limit; a write-timeout 524 can arrive much earlier. Distinguish it from [522](https://howhttpworks.com/status-codes/522) (connection/acknowledgement timeout) and [504](https://howhttpworks.com/status-codes/504) (gateway timeout). An origin nginx read timeout or ALB idle timeout can fire first; both default to 60 seconds.

## Common causes by stack

- **Cloudflare proxy:** the 125-second read or 30-second write limit produces 524. Establish which phase stalled before requesting an Enterprise read-timeout increase; the write limit is fixed.
- **nginx in front of an app:** log `$request_time`, `$upstream_response_time` and the forwarded `$http_cf_ray`. A high upstream time sends you to the app; inspect nginx buffering when testing streaming. [nginx log variables](https://nginx.org/en/docs/http/ngx_http_log_module.html), [upstream timings](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#variables).
- **Express, FastAPI, Django, Laravel or Rails behind Cloudflare:** a long-running report handler can leave Cloudflare waiting. Put the report in a background job and return a status URL promptly. Correlate the origin log with the job's database and downstream-call timings. Cloudflare emits the 524 in this arrangement; the framework may eventually log a completed request.
- **ALB or Kubernetes ingress behind Cloudflare:** check the inner proxy timeout as well as Cloudflare's. Raising an ingress read annotation or ALB idle limit cannot raise Cloudflare's limit; it can expose the outer 524 once the earlier 504 is removed. Inspect both access logs for the same request.

## Fix it

1. **Find the slow request.** Search origin logs for the Ray ID or the URL. Nginx: log `$request_time`. Look for requests where it nears 125 seconds.

   ```nginx
   log_format timed '$remote_addr "$request" $status $request_time $upstream_response_time ray=$http_cf_ray';
   access_log /var/log/nginx/timed.log timed;
   ```

2. **Make slow endpoints asynchronous.** Return [202 Accepted](https://howhttpworks.com/status-codes/202) with a status URL, process in a queue (Sidekiq, Celery, BullMQ), and poll or push the result. Exports, reports and bulk imports are the usual offenders.
3. **Fix the actual bottleneck**: missing database indexes, N+1 queries, locks, a downstream API without a timeout. Add explicit timeouts to outbound calls so your service fails before Cloudflare does.
4. **Test streaming through the proxy.** Flush real response chunks and inspect buffering at every hop. For an nginx streaming location, `proxy_buffering off;` forwards data as it arrives. Compare the direct and proxied stream before relying on it for long generation tasks.
5. **Bypass the proxy for heavy transfers.** Large uploads, long-poll or export endpoints can use an unproxied (grey cloud) subdomain, accepting that you lose Cloudflare protection on it.
6. **Raise timeouts consistently** if you have to: Enterprise plan for Cloudflare, plus `proxy_read_timeout`, application server timeouts (gunicorn `--timeout`, PHP `max_execution_time`) and load balancer idle timeout, otherwise a lower layer fails first.

### Reproduce

```bash
time curl -s -o /dev/null -w '%{http_code}\n' https://example.com/slow-endpoint
# 524 after ~125s
time curl -s -o /dev/null -w '%{http_code}\n' --resolve example.com:443:203.0.113.10 https://example.com/slow-endpoint
# the origin's real status and duration
```

## 524 vs related

| Code | Meaning                                                      |
| ---- | ------------------------------------------------------------ |
| 522  | Could not connect (or acknowledge) in time                   |
| 524  | Connected, then the origin read or write timeout expired     |
| 504  | A gateway timed out connecting or waiting for response data  |

## Related

- [522 Connection Timed Out](https://howhttpworks.com/status-codes/522)
- [504 Gateway Timeout](https://howhttpworks.com/status-codes/504)
- [202 Accepted](https://howhttpworks.com/status-codes/202)
- [520 Web Server Returned an Unknown Error](https://howhttpworks.com/status-codes/520)
- [526 Invalid SSL Certificate](https://howhttpworks.com/status-codes/526)
