Anthropic API Timeout: "Request Timed Out" — Diagnosis and Fixes
Quick answer
The official Anthropic SDKs apply a 10-minute default timeout and silently retry timeouts twice, so worst-case wall clock is timeout × 3. The single most effective fix is streaming — SSE keeps bytes flowing, so idle read timeouts never fire while the model is generating. For extended thinking and other long-reasoning requests, stream with a generous max_tokens instead of guessing at a short fixed timeout.
Symptoms and What They Mean
| Symptom | Where it fires | What it means |
|---|---|---|
anthropic.APITimeoutError (Python) | SDK client | Request exceeded the configured timeout; the SDK already retried |
APIConnectionTimeoutError (TypeScript) | SDK client | Same condition, TypeScript spelling |
ValueError before any request is sent (Python) | SDK guard | Non-streaming request estimated to exceed ~10 minutes — switch to streaming |
| HTTP 408 / 504 / 524 | Proxy, load balancer, CDN | An intermediate hop gave up before the origin finished |
| Stream cuts off after a long silent gap | Network path | An idle read timeout dropped the connection mid-generation |
A timeout is a client-side or infrastructure verdict, not a model error — the generation may still be running (or finished) server-side after your client gave up.
Why Timeouts Happen
- Long generations are legitimate. Current Claude models support 128K output tokens and adaptive extended thinking; hard reasoning tasks run many minutes in a single request.
- Non-streaming + large
max_tokens. The response arrives as one silent HTTP body; every hop must tolerate the full duration with zero bytes moving. - Read timeouts cap silence, not duration.
httpx/requestsread timeouts reset on every byte received — and a non-streaming LLM call is one long silence. - Intermediate infrastructure is stricter than your client. nginx
proxy_read_timeoutdefaults to 60 s; many CDNs drop idle connections around 100 s — far below the SDK's 10 minutes. - Upstream congestion. Slow time-to-first-token at peak load can push a normal request over an aggressive custom timeout.
Fix 1: Configure the Timeout Explicitly (Know Your Units)
The default is 10 minutes in every official SDK, but the units differ by language — a classic source of accidental 900 ms timeouts.
import anthropic
import httpx
# Python takes SECONDS
client = anthropic.Anthropic(timeout=900.0)
# Granular control via httpx.Timeout
client = anthropic.Anthropic(
timeout=httpx.Timeout(900.0, connect=5.0),
)
# Per-request override without mutating the client
client.with_options(timeout=120.0).messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Give me a one-paragraph summary of HTTP keep-alive."}],
)// TypeScript takes MILLISECONDS
const client = new Anthropic({ timeout: 900_000 });
// Per-request override
await client.messages.create({ /* ... */ }, { timeout: 120_000 });Go uses option.WithRequestTimeout(time.Duration), Java a Duration, C# a TimeSpan. Only the TypeScript SDK auto-scales the default (up to 60 minutes) for large non-streaming max_tokens — do not rely on that elsewhere.
Fix 2: Stream Anything Long
Streaming converts one long silent wait into a continuous trickle of small reads, so no read timeout on any hop ever sees an idle connection. This is why the Python SDK actively refuses non-streaming requests it estimates will exceed 10 minutes.
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=64000,
messages=[{
"role": "user",
"content": "Write a detailed migration plan for moving a monolith to microservices.",
}],
) as stream:
message = stream.get_final_message() # full Message object, timeout-safeNo token-by-token UI needed? get_final_message() (Python) / finalMessage() (TypeScript) still returns the complete response with streaming's timeout protection.
Fix 3: Extended Thinking Needs Minutes, Not Seconds
With adaptive thinking enabled, a single high-effort request can legitimately run 10+ minutes — that is the feature working, not a hang. Three rules:
- Always stream these requests; pair adaptive thinking with a large
max_tokens, since thinking tokens count against the output budget. - Control depth with effort levels, not with a tight timeout. Cutting the timeout truncates nothing gracefully — you pay for the tokens generated before the drop.
- Distinguish outcomes:
stop_reason: "max_tokens"means the output budget ran out (raisemax_tokens); a timeout exception means your clock ran out (stream, or raise the timeout).
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=64000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[{"role": "user", "content": "Prove or refute: every planar graph is 4-colorable. Walk through the reasoning."}],
) as stream:
message = stream.get_final_message()Fix 4: Retries and Idempotency
The SDKs retry connection errors, timeouts, 408, 409, 429 and 5xx with exponential backoff — 2 retries by default. Two consequences people miss:
- Wall clock multiplies. Worst case is
timeout × (max_retries + 1). A "10-minute" call can occupy a worker for 30 minutes. With a hard latency budget, cap both:
client = anthropic.Anthropic(timeout=60.0, max_retries=0)- Retries are at-least-once, not exactly-once. A client timeout does not cancel server-side generation; the timed-out attempt may still complete and be billed. If your pipeline has side effects (webhooks, DB writes), key each logical job with your own ID and dedupe on it.
Timeouts Through byesu
byesu is an AI API gateway with both OpenAI-compatible and Anthropic-native endpoints — one key covers Claude, GPT-5.6, Grok and Gemini, billed pay-as-you-go with no subscription. Timeout mechanics through the gateway are the same as calling upstream directly: your SDK timeout governs the whole chain, and streaming passes through end to end on both endpoint formats, so stream: true remains fix number one.
from openai import OpenAI
client = OpenAI(
api_key="sk-YOUR_TOKEN",
base_url="https://byesu.com/v1", # OpenAI-compatible format includes /v1
timeout=900.0,
)
stream = client.chat.completions.create(
model="claude-sonnet-5",
stream=True,
messages=[{"role": "user", "content": "Summarize the tradeoffs between SSE and WebSockets for LLM streaming."}],
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)The Anthropic-native format works the same way — point ANTHROPIC_BASE_URL at https://byesu.com (no /v1) and keep your existing streaming code. Billing is per token with transparent multipliers (input 1x / output 5x / cache hit 0.1x); the console shows your live billed price. Top up with USDT, Alipay or WeChat Pay. If a long request keeps failing, bisect: streaming on, smaller max_tokens, another model, another network path.
Related Links
- Quick Start (3 steps) — create a token · set the address · pick a model
- Common Errors & Fixes — 401, insufficient quota, no available channel, and more
- Console Sign-up / Create Token — get an
sk-token and see live pricing
FAQ
What is the default timeout in the Anthropic SDK?
The official Anthropic SDKs default to a 10-minute request timeout. Units differ by language: Python and Ruby take seconds, TypeScript takes milliseconds, and Go, Java and C# use native duration types. When the limit is hit, the SDK raises a timeout error (anthropic.APITimeoutError in Python) and automatically retries up to max_retries times, which is 2 by default.
How do I fix a Claude API request timeout?
Enable streaming first: server-sent events keep bytes flowing, so idle read timeouts never fire while the model is generating. If you must stay non-streaming, raise the client timeout explicitly and keep max_tokens around 16K or below.
Why does the Python SDK raise ValueError for large max_tokens without streaming?
The Python SDK refuses non-streaming requests it estimates will run longer than about 10 minutes, because idle HTTP connections tend to get dropped before the response completes. Pass stream=True, use client.messages.stream() with get_final_message(), or explicitly override the timeout to suppress the guard.
What timeout should I set for extended thinking requests?
Long-reasoning requests on current Claude models can legitimately run for many minutes in a single call. Use streaming with a generous max_tokens instead of a short fixed timeout; if you must set one, budget 10 minutes or more and remember that automatic retries multiply worst-case wall clock to timeout × (max_retries + 1).
Does the Anthropic SDK retry timed-out requests automatically?
Yes. Timeouts, connection errors, 408, 409, 429 and 5xx responses are retried with exponential backoff, 2 retries by default. A timed-out client request may still complete on the server, so treat retries as at-least-once delivery: give each logical job an ID of your own and dedupe downstream side effects.
Do timeouts behave differently through an API gateway like byesu?
The mechanics are the same: your SDK timeout governs the whole chain, and streaming passes through end to end on both the OpenAI-compatible and Anthropic-native endpoints. Enabling stream: true remains the single most effective fix, and once the first token arrives the request will not hit an idle read timeout.
