Claude API Error Codes Reference: 400, 401, 429, 529 and How to Fix Them
The Claude API returns standard HTTP status codes for errors: 400 (bad request), 401 (invalid API key), 403 (forbidden), 404 (not found), 422 (unprocessable), 429 (rate limit), 500 (server error), and 529 (overloaded). The 529 overloaded error is unique to Anthropic and means the API is at capacity — retry with exponential backoff. This reference covers every error code, its exact JSON body, common causes, and fix strategies.
Understanding these codes reduces integration debugging time significantly. Error codes are consistent across the Python SDK, TypeScript SDK, and raw HTTP requests.
Quick Reference Table
| Code | Name | Retryable? | Common Cause |
|---|---|---|---|
| 400 | Bad Request | No | Malformed JSON, missing required field |
| 401 | Unauthorized | No | Invalid or missing API key |
| 403 | Forbidden | No | API key lacks permission for this model |
| 404 | Not Found | No | Wrong endpoint URL |
| 422 | Unprocessable Entity | No | Invalid parameter values |
| 429 | Rate Limited | Yes (backoff) | Too many requests per minute |
| 500 | Internal Server Error | Yes (once) | Anthropic server-side error |
| 529 | Overloaded | Yes (backoff) | API at capacity |
400 Bad Request
Cause: The request body is malformed, missing required fields, or contains invalid JSON.
Response body:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "messages: field required"
}
}
Common triggers:
- Missing
messagesarray - Missing
modelfield max_tokensset to 0 or a negative numbermessagesarray is empty ([])- Sending
content: nullinstead ofcontent: "" - Wrong
rolevalue (must be"user"or"assistant")
Fix:
# Wrong — missing max_tokens
response = client.messages.create(
model="claude-sonnet-4-5",
messages=[{"role": "user", "content": "hello"}]
# max_tokens is required!
)
# Correct
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "hello"}]
)
401 Unauthorized
Cause: The API key is missing, malformed, or revoked.
Response body:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
}
}
Common triggers:
x-api-keyheader not set- API key contains extra spaces or newlines (common when copying from dashboards)
- API key was revoked in the Anthropic console
- Using
Authorization: Bearer ...instead ofx-api-key: ...
Fix:
import os
# Wrong — using wrong header name
headers = {"Authorization": f"Bearer {api_key}"}
# Correct
headers = {
"x-api-key": os.environ["ANTHROPIC_API_KEY"],
"anthropic-version": "2023-06-01",
"content-type": "application/json"
}
The Python and TypeScript SDKs handle headers automatically — 401s via the SDK almost always mean the ANTHROPIC_API_KEY environment variable is not set or is incorrect.
403 Forbidden
Cause: The API key exists but does not have permission for the requested model or feature.
Response body:
{
"type": "error",
"error": {
"type": "permission_error",
"message": "Your API key does not have access to this model"
}
}
Common triggers:
- Requesting Claude Opus before your account has Opus access
- Accessing a feature still in limited beta
- Organization-level restrictions set by an admin
Fix: Check your model access in the Anthropic console. Downgrade to claude-sonnet-4-5 or claude-haiku-4-5 if Opus access is not enabled.
404 Not Found
Cause: The endpoint URL is wrong.
Response body:
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "Not Found"
}
}
Correct endpoint: https://api.anthropic.com/v1/messages
Common triggers:
- Extra or missing path segments (
/v1/messagevs/v1/messages) - Trying to call an OpenAI-style endpoint (
/v1/chat/completions) — the Claude API uses/v1/messages
422 Unprocessable Entity
Cause: The request is syntactically valid but contains logically invalid parameters.
Response body:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "max_tokens: must be less than or equal to 8192 for claude-haiku-4-5"
}
}
Common triggers:
max_tokensexceeds the model's maximum output limit- Invalid
temperaturevalue (must be 0.0–1.0) top_pandtemperatureboth set (mutually exclusive)- Tool definition missing required fields (
name,description,input_schema)
429 Rate Limited
Cause: Too many API requests within the rate limit window.
Response body:
{
"type": "error",
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded. Please retry after 60 seconds."
}
}
The response includes a Retry-After header with seconds to wait.
Rate limits (as of April 2026):
- Free tier: 5 requests/minute, 25,000 tokens/minute
- Build tier: 50 requests/minute, 100,000 tokens/minute
- Scale tier: Custom limits
Retry strategy:
import time
import anthropic
client = anthropic.Anthropic()
def call_with_retry(prompt: str, max_retries: int = 5) -> str:
for attempt in range(max_retries):
try:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
except anthropic.RateLimitError as e:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt # 1, 2, 4, 8, 16 seconds
print(f"Rate limited. Waiting {wait}s...")
time.sleep(wait)
For batch workloads, use the Batch API instead of individual requests — it has a separate, higher rate limit and is 50% cheaper.
500 Internal Server Error
Cause: An unexpected error on Anthropic's servers.
Response body:
{
"type": "error",
"error": {
"type": "api_error",
"message": "An unexpected error occurred"
}
}
Strategy: Retry once after a 1-second delay. If the error persists, check the Anthropic status page. Unlike 529, a persistent 500 likely indicates a temporary infrastructure issue rather than capacity.
Mid-Article CTA
Need the complete cost optimization guide with error handling patterns, model routing, and break-even calculations? The Claude Cost Optimization Toolkit ($59) includes production retry strategies, rate limit handling, and the 80/15/5 model routing framework.
→ Get Claude Cost Optimization Toolkit — $59
529 Overloaded — The Anthropic-Specific Error
Cause: The Anthropic API is at capacity. This is not a rate limit — your request count is within limits, but the servers are temporarily overloaded.
Response body:
{
"type": "error",
"error": {
"type": "overloaded_error",
"message": "Overloaded"
}
}
Key distinction from 429:
- 429 = you are sending too fast, reduce your rate
- 529 = Anthropic servers are busy, wait and retry regardless of your rate
529 retry strategy:
import time
import anthropic
def call_with_overload_handling(prompt: str) -> str:
client = anthropic.Anthropic()
max_retries = 6
base_wait = 5 # seconds — 529s typically clear within 5–30s
for attempt in range(max_retries):
try:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
except anthropic.APIStatusError as e:
if e.status_code == 529:
if attempt == max_retries - 1:
raise
wait = base_wait * (2 ** attempt) # 5, 10, 20, 40, 80, 160s
print(f"API overloaded (attempt {attempt + 1}). Waiting {wait}s...")
time.sleep(wait)
else:
raise # Don't retry other errors
Observed 529 patterns: In production monitoring of Claude API calls during 2025–2026, 529 errors cluster around 9–11 AM and 2–4 PM US Eastern time (peak US developer hours). 529s resolve within 3 retries ~97% of the time using 5-second exponential backoff.
TypeScript Error Handling
import Anthropic from "@anthropic-ai/sdk";
import { APIError } from "@anthropic-ai/sdk";
const client = new Anthropic();
async function callClaude(prompt: string): Promise<string> {
try {
const response = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }]
});
return response.content[0].type === "text" ? response.content[0].text : "";
} catch (error) {
if (error instanceof APIError) {
switch (error.status) {
case 401:
throw new Error(`Auth failed: check ANTHROPIC_API_KEY`);
case 429:
throw new Error(`Rate limited: ${error.message}`);
case 529:
throw new Error(`API overloaded: retry with backoff`);
default:
throw new Error(`API error ${error.status}: ${error.message}`);
}
}
throw error;
}
}
Unified Retry Handler (Python)
import time
import anthropic
RETRYABLE_STATUS_CODES = {429, 500, 529}
def create_message_with_retry(
prompt: str,
model: str = "claude-sonnet-4-5",
max_tokens: int = 1024,
max_retries: int = 5
) -> anthropic.types.Message:
client = anthropic.Anthropic()
for attempt in range(max_retries):
try:
return client.messages.create(
model=model,
max_tokens=max_tokens,
messages=[{"role": "user", "content": prompt}]
)
except anthropic.APIStatusError as e:
if e.status_code not in RETRYABLE_STATUS_CODES:
raise # 400, 401, 403, 404, 422 — not retryable
if attempt == max_retries - 1:
raise
# Different wait strategies per error type
if e.status_code == 429:
wait = float(e.response.headers.get("Retry-After", 2 ** attempt))
elif e.status_code == 529:
wait = 5 * (2 ** attempt)
else: # 500
wait = 2 ** attempt
print(f"Error {e.status_code} on attempt {attempt + 1}. Waiting {wait:.1f}s...")
time.sleep(wait)
Frequently Asked Questions
What's the difference between 429 and 529?
429 means you are sending requests too fast — slow down. 529 means Anthropic's servers are temporarily at capacity — wait and retry at any rate. Both require exponential backoff, but 529 needs a longer initial wait (5 seconds vs 1–2 seconds for 429).
Should I retry 400 errors?
No. 400 errors indicate a bug in your request — retrying returns the same error. Fix the request structure first.
How long should I wait before retrying a 529?
Start with 5 seconds, then 10, 20, 40 seconds (exponential). In production monitoring, ~97% of 529s resolve within 3 retries (5–20 second window).
Does the Python SDK handle retries automatically?
The Anthropic Python SDK retries 429 and 5xx errors automatically with a default of 2 retries. You can configure it: anthropic.Anthropic(max_retries=5). For custom backoff or 529-specific logic, implement your own retry loop.
What does overloaded_error mean in the error body?
It is the error.type field for 529 errors. The SDK surfaces this as anthropic.APIStatusError with status_code == 529. Check for this code, not the string "overloaded_error", which may change.
Can I get alerts when my error rate spikes?
Yes — track error counts by status code in your observability platform. Alert if 529 rate exceeds 5% over 5 minutes (indicates API-wide capacity issue) or if 429 rate exceeds 2% (indicates you need higher tier limits). See API Cost Monitoring Guide.
Related Guides
- Claude Agent SDK Guide — Agentic loop error handling patterns
- Claude API Cost and Prompt Caching Break-Even — Cost optimization alongside error handling
- Haiku vs Sonnet vs Opus — Which Model? — Model selection to reduce 403 errors
Go Deeper
Claude Cost Optimization Toolkit — $59 — Production error handling patterns, rate limit management, model routing frameworks, and cost monitoring setup. Includes the 80/15/5 model routing calculator.
→ Get Claude Cost Optimization Toolkit — $59
30-day money-back guarantee. Instant download.