LLM API timeout errors: which layer actually killed your request

Both major SDKs default to a ten-minute timeout, and almost nothing in a real deployment lets a request live that long. The layer that kills it is nearly always one you did not configure, and the shape of the failure tells you which one.

By the Continuum team. We build a workbench that runs Claude Code, Codex, and their peers, so the model rates quoted here are the ones our own cost analytics ship with.

The short version

A timeout on an LLM call is a race between layers, and the tightest one wins. The OpenAI and Anthropic Python SDKs both default to 600 seconds total with a 5 second connect timeout. Cloudflare's Proxy Read Timeout is 125 seconds, an AWS ALB idles out at 60, nginx reads for 60, and Vercel and Cloud Run both stop at 300. So the SDK timeout is almost never the one that fires. Identify the layer from the failure shape: an SDK APITimeoutError is yours, a Cloudflare-branded 524 HTML page is the CDN, and an unbranded blank 504 is something else in the path. Streaming fixes most of it, because a proxy read timeout measures the gap between reads rather than the total duration.

What you need to know
  • SDK defaults are 600 seconds total, 5 seconds connect, on both OpenAI and Anthropic Python clients.
  • Cloudflare's 524 fires at 125 seconds, not the 100 that most articles still quote.
  • An ALB idles out at 60 seconds and explicitly does not reset on HTTP/2 PING frames.
  • Streaming resets the read clock. A proxy read timeout measures the gap between reads, not the total.
  • Anthropic SDKs refuse a non-streaming request expected to exceed ten minutes, before sending it.
  • A 504 timeout_error from Anthropic is the server timing out, not your client.
  • For long agent turns the answer is resume, not retry: background mode, or the Batch API.

Three timeouts, and the one everybody sets

A single HTTP call has several independent clocks, and conflating them is why "we set a timeout" so often fails to fix anything.

ClockMeasuresRight value for LLM calls
ConnectTCP and TLS handshakeShort. 5 to 10 seconds. A slow handshake is a network fault, not a slow model
ReadGap between successive bytesGenerous while streaming, since gaps are short even on long generations
TotalWhole request, first byte to lastThe one that must match your product, not your patience
PoolWaiting for a free connectionShort. Exhaustion here is a concurrency bug

Getting this wrong in the usual direction, one large total timeout and nothing else, means a request to a black-holed host waits the full total before failing, when a five-second connect timeout would have failed it immediately and let a retry succeed.

Client defaults, checked August 2026 from source and docs.
ClientConnectReadTotal
OpenAI Python SDK5sn/a600s, 2 retries
Anthropic Python SDK5sn/a600s, 2 retries
Anthropic TypeScript SDK600s minimum, scaling with max_tokens up to 60 minutes
Python httpx5s5s5s (all four phases)
Python requestsnonenonenone
Node fetch / undici10s300s body, 300s headersnone

The layer that actually killed it

Here is the crux. Both major SDKs wait ten minutes; almost nothing between you and them does. Line up the real numbers and the winner is obvious.

Every ceiling in a typical path, tightest first.checked aug 2026
LayerDefaultStatus on breachRaisable?
AWS ALB idle timeout60s504Yes, 1 to 4000s
nginx proxy_read_timeout60s504Yes
Cloudflare Proxy Write Timeout30s524No
Cloudflare Proxy Read Timeout125s524Enterprise only, up to 6,000s
Vercel functions300sFunction timeoutPro and Enterprise to 800s, 1800s in beta
Cloud Run request timeout300s504Yes, to 3,600s
OpenAI / Anthropic SDK600sAPITimeoutErrorYes
Cloudflare Proxy Idle Timeout900s520No

The failure shape tells you which layer without any instrumentation:

What you seeWho did it
APITimeoutError from the SDKYour client. You own this number
Cloudflare-branded 524 HTML pageCloudflare, at 125s of read silence
Cloudflare-branded 502 or 504Your origin returned it
Unbranded blank 502 or 504Cloudflare itself generated it
504 with a JSON body and timeout_errorAnthropic's own server-side timeout
Connection reset with no statusA load balancer or middlebox dropped the socket
522Cloudflare could not reach your origin at all

That branded-versus-unbranded distinction for 502 and 504 is one of the more useful facts in Cloudflare's documentation and almost nobody knows it.

Streaming is not an optimisation, it is the fix

Most intermediate timeouts are inactivity timeouts, not duration limits. Cloudflare defines the Proxy Read Timeout precisely as "a timeout value between two successive read operations to your origin server". So a response emitting tokens every few hundred milliseconds resets that clock continuously and can run far longer than 125 seconds. A non-streaming request producing nothing for three minutes cannot.

Anthropic enforces the same conclusion from the other end, and does it in the client so you cannot get it wrong quietly:

The user-facing wording of that guard is Streaming is required for operations that may take longer than 10 minutes. The TypeScript SDK takes a different route to the same place, scaling the default timeout with max_tokens up to sixty minutes rather than refusing. And the API side has its own dedicated status for this: a 504 timeout_error, documented as "the request timed out while processing", with the recommendation to use the streaming Messages API for long-running requests.

If you do not want incremental tokens, the SDK will still assemble the final message for you. There is no reason not to stream.
with client.messages.stream(
    model="claude-sonnet-5",
    max_tokens=64000,
    messages=messages,
) as stream:
    message = stream.get_final_message()   # identical to a non-streaming result

Timeouts worth setting, by operation

One global timeout cannot serve an autocomplete and a repository-wide refactor. Set them per operation, and set them from the product requirement rather than from the model.

A starting table. Tune from your own p99, not from these.
OperationConnectTotalStream?Retries
Classification, extraction, short answers5s30sNo2
Chat turn with a human waiting5s120sYes1
Reasoning at high effort5s600sYes1
Agent turn with tool calls5s900s per turnYes0, resume instead
Long document generation5sSDK defaultRequired1
Bulk offline workn/an/an/aUse the Batch API
Per-request overrides beat one client-level compromise.
from openai import OpenAI
import httpx2

client = OpenAI(
    timeout=httpx2.Timeout(120.0, connect=5.0),
    max_retries=2,
)

# a specific call that legitimately needs longer
resp = client.with_options(timeout=600.0).responses.create(
    model="gpt-5.6-sol",
    input=big_prompt,
)
  • Raise every layer together or none. Raising the SDK timeout to 900 seconds behind a 60 second ALB changes nothing except which error you see.
  • Keep the connect timeout short always. It is the one number that should never scale with the work.
  • Budget the whole chain. If your API gateway allows 30 seconds, an LLM call inside it cannot have a 120 second timeout in any meaningful sense.
  • Do not retry a timeout blind on an agent turn. The turn may have already run tools. This is the same duplicate-execution problem retries cause on 5xx errors.

Retry, or resume?

For a stateless completion, retrying a timeout is correct and cheap. For an agent turn it is neither, because you do not know how far the turn got, and a replay can re-execute side effects that already happened. Past roughly a minute of work, the right pattern stops being retry and becomes resume.

PatternGood forCost
Retry the whole callShort stateless requestsDuplicate work, duplicate tokens
Stream and checkpointLong generationsYou keep the partial output on a drop
Background modeLong single requestsHigher time to first token; poll or resume by ID
Batch APIAnything with nobody waitingLatency, in exchange for roughly half the price
Turn-level checkpointingAgent loopsYou build it, and it is the only thing that really works

OpenAI documents background mode for exactly this: send background: true, poll while the response is queued or in_progress, and resume a stream from a sequence_number instead of replaying the turn. Two caveats from the same page: time to first token is higher than a synchronous call, and cancellation is idempotent even though the inference endpoints have no idempotency key. There is also a hard ceiling on the WebSocket surface, sixty minutes, with the error Responses websocket connection limit reached (60 minutes). Create a new websocket connection to continue.

Anthropic's equivalent is the Message Batches API, recommended in the errors documentation as the alternative to holding an uninterrupted connection, and priced at half rate in both directions.

Questions people ask

What is the default timeout for the OpenAI and Anthropic APIs?

Both Python SDKs default to 600 seconds total with a 5 second connect timeout, and both retry twice by default. The Anthropic TypeScript SDK uses 600 seconds as a floor and scales it with max_tokens up to sixty minutes. In practice these rarely fire, because something between you and the provider is stricter.

What causes a Cloudflare 524 on an API call?

Cloudflare reached your origin but got no response before the Proxy Read Timeout, which defaults to 125 seconds. Enterprise zones can raise it to 6,000 seconds through a Cache Rule read_timeout setting or the zone settings API; other plans cannot. A separate 30 second Proxy Write Timeout also returns 524 and cannot be adjusted at all.

Does streaming prevent timeout errors?

It prevents most of them. Cloudflare defines its Proxy Read Timeout as a timeout between two successive read operations, so a response emitting tokens continuously keeps resetting that clock. Cloudflare never states outright that streaming prevents a 524, but the definition of the setting points clearly that way, and Anthropic's SDKs go further by refusing a non-streaming request expected to run beyond ten minutes.

Why does my request time out at 60 seconds when I set 600?

Because your timeout is not the binding one. An AWS ALB idles out at 60 seconds by default and nginx reads for 60, so either will kill the connection long before an SDK configured for ten minutes notices. Raising a timeout only helps if you raise every layer between the client and the provider.

Should I retry a timed-out LLM request?

For a short stateless call, yes, and both SDKs already retry timeouts twice by default. For an agent turn, no: the turn may have already executed tools, and replaying it can run those side effects again. Use background mode, the Batch API, or turn-level checkpointing so you can resume rather than restart.

What is the difference between a 504 from Anthropic and a 524 from Cloudflare?

Anthropic's 504 timeout_error is the API server itself giving up while processing, and it arrives as a JSON error body with the documented advice to use the streaming Messages API. A 524 is Cloudflare giving up waiting for an origin, and it arrives as a branded HTML page. If you can see Cloudflare branding, the request never came back from whatever sits behind Cloudflare in your own path.

Sources

Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.

  1. Cloudflare error 524 the 125 second Proxy Read Timeout and the Enterprise ceiling
  2. Cloudflare connection limits every Cloudflare-to-origin timeout and the status each returns
  3. Claude API errors: long requests 504 timeout_error and the ten-minute streaming guidance
  4. Anthropic Python SDK default timeout, the non-streaming ValueError guard, TCP keep-alive
  5. OpenAI background mode polling, stream resumption, idempotent cancellation
  6. AWS ALB load balancer attributes 60 second idle default and HTTP/2 PING behaviour
  7. undici Client API Node fetch header, body, and connect timeout defaults
Try it

The turn outlives
the connection.

Continuum drives Claude Code, Codex, and peers under your own subscriptions, with live quota gauges and spend by repo. The app is free. Mac is stable; Windows and Linux desktop are beta.

free app · your subscriptions · local-first