Cloudflare API Timeout: How to Diagnose and Fix 524, 522, and Request Timeout Errors
Fix Cloudflare API timeout errors (524, 522, 408) by tuning origin response times, adjusting Worker CPU limits, and using Cloudflare's retry APIs. Step-by-step
- Cloudflare enforces a hard 100-second origin response timeout on all plans; if your origin does not respond within that window, Cloudflare returns a 524 (A Timeout Occurred) error to the client
- The Cloudflare REST Management API (api.cloudflare.com) can return 429 Too Many Requests or drop connections due to client-side TCP timeouts when the caller's HTTP client has a shorter timeout than the API response latency under load
- Cloudflare Workers have a 50 ms CPU time limit on the Free plan and 30 s on Paid; long-running synchronous compute triggers a 1101 Worker threw exception or a silent timeout that manifests as a 524 downstream
- Quick fix hierarchy: (1) increase origin response time or offload slow work to async queues, (2) set a suitably long HTTP client timeout when calling api.cloudflare.com, (3) split heavy Worker logic into Durable Objects or Queue consumers
| Method | When to Use | Estimated Time to Implement | Risk |
|---|---|---|---|
| Increase Cloudflare Proxy Timeout via Page Rule / Config Rule | Origin is legitimately slow (reports, exports, DB queries > 100 s) and you control the zone | 30 minutes | Low — only affects matched paths |
| Set long timeout in your API client (axios, requests, curl) | Your code calls api.cloudflare.com and drops the TCP connection before Cloudflare responds | 5 minutes | Low — client-side change only |
| Move slow logic to a background job / queue | Origin endpoint does heavy processing synchronously | 1–3 days | Medium — requires application refactor |
| Enable Cloudflare Tiered Cache / Cache Rules | Repeated identical API calls are timing out due to cache misses on slow origins | 1 hour | Low — additive caching layer |
| Migrate heavy Worker logic to Durable Objects or Queues | Worker CPU time limit exceeded on Free/Paid plan | 1–2 days | Medium — architecture change |
| Upgrade Cloudflare plan for extended timeout limits | Enterprise timeout (6000 s) required for very long-running jobs | Hours (commercial) | Low — plan change |
| Implement exponential backoff & retry on 524/522 | Intermittent timeouts due to origin spikes | 2–4 hours | Low — defensive coding |
Understanding Cloudflare API Timeout Errors
The term "Cloudflare API timeout" covers two distinct failure scenarios that are often confused:
- Cloudflare acting as a reverse proxy: Your end-users hit your domain and Cloudflare cannot get a response from your origin server within the allowed time window. This produces HTTP
524 A Timeout Occurredor522 Connection Timed Out. - Your code calling the Cloudflare Management API (
https://api.cloudflare.com/client/v4/...): Your HTTP client drops the connection or Cloudflare returns408 Request Timeout/429 Too Many Requestsbefore the API call completes.
Both scenarios share a root cause: a mismatch between how long a party is willing to wait and how long the operation actually takes.
Cloudflare Timeout Error Codes at a Glance
| Error Code | Meaning | Where it Originates |
|---|---|---|
522 Connection Timed Out |
Cloudflare could not complete the TCP handshake to your origin within 15 s | Cloudflare edge |
523 Origin Is Unreachable |
DNS or routing failure to origin | Cloudflare edge |
524 A Timeout Occurred |
TCP connected but origin did not send an HTTP response within 100 s | Cloudflare edge |
408 Request Timeout |
Client too slow sending the request body | Cloudflare or origin |
1101 Worker threw exception |
Worker runtime error, often from a timed-out fetch() inside a Worker |
Cloudflare Workers runtime |
429 Too Many Requests |
Rate limit hit on api.cloudflare.com | Cloudflare API |
Step 1: Confirm Which Timeout You Are Hitting
Before making any changes, identify the exact error code and origin.
Check browser DevTools or your HTTP client log:
HTTP/1.1 524 A Timeout Occurred
cf-ray: 8a3f1c2d4e5b6a7b-AMS
The cf-ray header confirms Cloudflare is involved. A 524 means Cloudflare reached your origin but your origin stalled.
Check Cloudflare dashboard logs:
- Go to Analytics & Logs → HTTP Requests in the Cloudflare dashboard.
- Filter by
Edge Status Code = 524or522. - Note which paths are affected and whether the pattern is consistent or intermittent.
Test origin bypass:
# Call origin directly (replace with your server IP) bypassing Cloudflare
curl -v --max-time 120 -H "Host: yourdomain.com" http://YOUR_ORIGIN_IP/slow-endpoint
If this also times out, the problem is in your application. If it succeeds within 100 s, Cloudflare's timeout window is the constraint.
Step 2: Fix 524 Errors (Origin Doesn't Respond in Time)
Option A — Speed Up the Origin
This is always the preferred fix. Profile the slow endpoint:
# Time the endpoint from the same network as your origin
curl -w "\nTotal: %{time_total}s\n" -o /dev/null -s http://localhost/slow-endpoint
Common culprits:
- Unindexed database queries — add indexes, use
EXPLAIN ANALYZE - Synchronous file I/O blocking the event loop (Node.js) — use streams or worker threads
- External HTTP calls inside the request path — move to async queues (Celery, BullMQ, Cloudflare Queues)
Option B — Extend the Cloudflare Timeout via Config Rules (Pro plan and above)
Cloudflare exposes the proxy_read_timeout setting via Configuration Rules:
- Go to Rules → Configuration Rules in the dashboard.
- Create a rule matching your slow path (e.g.,
http.request.uri.path contains "/export"). - Set Proxy Read Timeout to up to
6000seconds (Enterprise) or up to100seconds override on Pro.
Alternatively, use the Cloudflare API to create the rule programmatically:
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/rulesets/phases/http_config_settings/entrypoint" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": [{
"action": "set_config",
"action_parameters": {
"read_timeout": 300
},
"expression": "http.request.uri.path contains \"/export\"",
"description": "Extend timeout for export endpoint"
}]
}'
Note: Free plans cannot extend the 100 s limit. You must optimize the origin or upgrade.
Option C — Return 202 Accepted + Poll Pattern
For operations that genuinely take minutes, restructure the API:
- Endpoint immediately returns
202 Acceptedwith a job ID. - Client polls a
/jobs/{id}/statusendpoint. - Heavy work runs in a background worker.
This eliminates the timeout entirely because no single HTTP response takes long.
Step 3: Fix Cloudflare Management API Timeouts
When your code calls https://api.cloudflare.com/client/v4/... and the connection drops:
Symptom
Error: connect ETIMEDOUT api.cloudflare.com:443
Error: read ECONNRESET
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='api.cloudflare.com', port=443)
Root Causes
- Your HTTP client has a default timeout shorter than the API response latency (common defaults:
axios= no timeout,requestsPython = no timeout,curl= no timeout unless set) - Bulk operations (e.g., purging thousands of cache tags) take longer than expected
- Rate limiting causes the server to queue your request, exceeding client timeout
Fix: Set Explicit Timeouts and Retry Logic
See the code_block section for a complete example. Key principles:
- Set
timeoutto at least 30 s for simple calls, 120 s for bulk operations - Respect the
Retry-Afterheader on429responses - Use exponential backoff: wait 1 s, 2 s, 4 s, 8 s before retrying
Step 4: Fix Cloudflare Worker Timeouts
Workers on the Free plan get 10 ms CPU time per request (wall-clock: 30 s). Paid plan: 50 ms CPU / 30 s wall-clock. Exceeding these limits produces:
Error 1101: Worker threw exception
or a silent 524 passed through to the client.
Diagnose:
# Use wrangler tail to stream live Worker logs
npx wrangler tail MY_WORKER_NAME --format=pretty
Look for CPU time exceeded or Script execution timed out.
Fix options:
- Move CPU-heavy work to a Durable Object alarm (runs async, not in request path)
- Use Cloudflare Queues to defer processing
- Offload compute to a dedicated microservice via a subrequest with
waitUntil()
// Use waitUntil to defer non-critical work past response
export default {
async fetch(request, env, ctx) {
const response = new Response('Accepted', { status: 202 });
ctx.waitUntil(env.MY_QUEUE.send({ url: request.url }));
return response;
}
};
Step 5: Monitor and Alert
Set up proactive monitoring so timeouts don't surprise you:
# Cloudflare Analytics API — query 5xx rates for the last hour
curl "https://api.cloudflare.com/client/v4/zones/ZONE_ID/analytics/dashboard?since=-60&until=0" \
-H "Authorization: Bearer YOUR_API_TOKEN" | \
jq '.result.totals.requests.http_status | {"524": ."524", "522": ."522"}'
Consider:
- Cloudflare Health Checks (under Traffic → Health Checks) to get alerted when origin latency exceeds a threshold
- Cloudflare Notifications → Zone Analytics anomalies for 5xx spike alerts
- Grafana + Cloudflare Logpush for detailed per-path latency histograms
Frequently Asked Questions
#!/usr/bin/env bash
# cloudflare_timeout_diagnostics.sh
# Run this to diagnose Cloudflare API timeout issues
set -euo pipefail
ZONE_ID="YOUR_ZONE_ID"
API_TOKEN="YOUR_API_TOKEN"
ORIGIN_IP="YOUR_ORIGIN_IP"
DOMAIN="yourdomain.com"
SLOW_PATH="/api/slow-endpoint"
echo "=== 1. Check recent 524/522 errors via Cloudflare Analytics API ==="
curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/analytics/dashboard?since=-60&until=0" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" | \
jq '.result.totals.requests.http_status | {"522": (."522" // 0), "524": (."524" // 0)}'
echo ""
echo "=== 2. Time origin directly (bypass Cloudflare proxy) ==="
curl -v --max-time 120 \
-H "Host: ${DOMAIN}" \
-w "\n--- Timing ---\nDNS lookup: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS handshake: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
-o /dev/null -s \
"http://${ORIGIN_IP}${SLOW_PATH}"
echo ""
echo "=== 3. Check if Cloudflare IPs are whitelisted on origin firewall ==="
# Fetch Cloudflare IP ranges
curl -s https://www.cloudflare.com/ips-v4 | while read -r cidr; do
echo "Cloudflare range: ${cidr}"
done
echo ""
echo "=== 4. Inspect existing Configuration Rules (proxy timeout overrides) ==="
curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/rulesets" \
-H "Authorization: Bearer ${API_TOKEN}" | \
jq '.result[] | select(.phase == "http_config_settings") | {id, name, phase}'
echo ""
echo "=== 5. Create a Config Rule to extend timeout for slow path ==="
# Uncomment to apply:
# curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/rulesets/phases/http_config_settings/entrypoint" \
# -H "Authorization: Bearer ${API_TOKEN}" \
# -H "Content-Type: application/json" \
# -d "{
# \"rules\": [{
# \"action\": \"set_config\",
# \"action_parameters\": { \"read_timeout\": 300 },
# \"expression\": \"http.request.uri.path contains \\\"${SLOW_PATH}\\\"\",
# \"description\": \"Extended timeout for slow endpoint\"
# }]
# }"
echo ""
echo "=== 6. Python client with proper timeout + retry (print as reference) ==="
cat << 'PYTHON'
import httpx
import time
def cf_api_call_with_retry(url: str, token: str, payload: dict, max_retries: int = 4):
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
backoff = 1
for attempt in range(max_retries):
try:
with httpx.Client(timeout=httpx.Timeout(30.0, connect=10.0)) as client:
resp = client.post(url, json=payload, headers=headers)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", backoff))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
backoff *= 2
continue
resp.raise_for_status()
return resp.json()
except httpx.ReadTimeout:
print(f"Timeout on attempt {attempt + 1}, retrying in {backoff}s...")
time.sleep(backoff)
backoff = min(backoff * 2, 60)
raise RuntimeError(f"Failed after {max_retries} attempts")
PYTHON
echo ""
echo "=== 7. Stream live Worker logs with wrangler ==="
echo "Run: npx wrangler tail YOUR_WORKER_NAME --format=pretty"
echo "Look for: 'CPU time exceeded' or 'Script execution timed out'"
echo ""
echo "=== Diagnostics complete ==="Error Medic Editorial
Error Medic Editorial is a team of senior DevOps and SRE engineers with hands-on experience operating high-traffic applications behind Cloudflare. The team specializes in networking troubleshooting, CDN configuration, and API reliability patterns.
Sources
- https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/
- https://developers.cloudflare.com/rules/configuration-rules/settings/#proxy-read-timeout
- https://developers.cloudflare.com/workers/platform/limits/
- https://developers.cloudflare.com/api/
- https://community.cloudflare.com/t/524-timeout-errors-explanation-and-solutions/
- https://developers.cloudflare.com/queues/
- https://stackoverflow.com/questions/tagged/cloudflare+timeout