Claude API 429 限流报错怎么办?3 种重试方案
Claude API 返回 429(rate_limit_error)说明你的请求在短时间内超出了组织的速率上限,并非鉴权或代码出错。处理它的核心只有三步:先读取响应头判断是哪类限流,再用带抖动的指数退避自动重试,最后从架构上降低请求峰值。下面给出三种可直接落地的重试方案。
先搞清楚 429 是怎么来的
Claude 的 Messages API(POST /v1/messages)在组织维度上对每个模型分别计量三种速率,任意一种超限都会触发 429:
- RPM(Requests Per Minute):每分钟请求数。批量并发调用时最容易撞到。
- ITPM(Input Tokens Per Minute):每分钟输入 Token 数。长文档、长上下文场景的主要瓶颈。
- OTPM(Output Tokens Per Minute):每分钟输出 Token 数。大量生成任务时受限。
不同模型(Claude Opus 4.8、Claude Sonnet 4.6、Claude Haiku 4.5)配额各不相同,且和账户的使用等级(Usage Tier)挂钩。具体限额数字会随等级变化,具体以 Anthropic 官网为准。要区分 429 和 401,可参考 Claude API 报错 401 怎么解决?认证失败排查指南——401 是 API Key 问题,429 是频率问题,两者排查方向完全不同。
读懂响应头:限流自带"何时重试"的提示
每次返回 429 时,HTTP 响应头里会带上关键信息,先看它再决定怎么重试,能避免盲目空转:
| 响应头 | 含义 |
|---|---|
retry-after | 建议等待的秒数,直接照做即可 |
anthropic-ratelimit-requests-remaining | 当前窗口剩余可用请求数 |
anthropic-ratelimit-tokens-remaining | 当前窗口剩余可用 Token 数 |
anthropic-ratelimit-requests-reset | 请求配额重置的时间戳 |
哪一项 remaining 先归零,就说明你撞的是哪种限流。如果是 tokens 先到 0,多半要从压缩上下文入手,可以看 Claude API 怎么省钱?5 个降低 Token 成本的方法。
方案一:用官方 SDK 自带的自动重试(最省事)
Anthropic 官方 SDK(Python 的 anthropic、Node 的 @anthropic-ai/sdk)默认就会对 429、408、5xx 等错误自动重试,并采用带抖动的指数退避,还会优先遵守 retry-after。你只需要调高重试次数即可:
from anthropic import Anthropic
# 默认重试 2 次,这里调到 5 次
client = Anthropic(max_retries=5)
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "用一句话解释什么是限流"}],
)
print(msg.content[0].text)
Node.js 写法同理:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ maxRetries: 5 });
const msg = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{ role: "user", content: "用一句话解释什么是限流" }],
});
console.log(msg.content[0].text);
SDK 安装与基础配置见 Anthropic Python SDK 安装与配置完整教程。如果你还没跑通第一个请求,建议先看 Claude API Python 示例代码:10 分钟跑通第一个程序。
方案二:手动实现指数退避 + 抖动(可控性最强)
当你需要自定义重试逻辑——比如对接消息队列、记录每次重试日志、或在多线程里精细控制——就自己写退避。核心是每次失败后等待时间翻倍,再叠加随机抖动,避免多个客户端同时重试造成"重试风暴":
import time, random
from anthropic import Anthropic, RateLimitError
client = Anthropic(max_retries=0) # 关掉 SDK 重试,自己接管
def call_with_backoff(messages, max_attempts=6):
for attempt in range(max_attempts):
try:
return client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages,
)
except RateLimitError as e:
if attempt == max_attempts - 1:
raise
# 优先用服务端给的 retry-after
retry_after = e.response.headers.get("retry-after")
if retry_after:
wait = float(retry_after)
else:
wait = min(2 ** attempt, 60) + random.uniform(0, 1)
print(f"429 限流,第 {attempt+1} 次重试,等待 {wait:.1f}s")
time.sleep(wait)
resp = call_with_backoff([{"role": "user", "content": "你好"}])
print(resp.content[0].text)
几个要点:等待上限用 min(..., 60) 封顶,避免退避到几分钟;抖动用 random.uniform 打散并发;服务端有 retry-after 时一律以它为准。Node.js 端逻辑一致,可结合 Claude API Node.js 调用示例:从安装到流式输出 改写。
方案三:从源头降峰——限流不是只能"硬扛"
重试只是兜底,真正稳定的做法是别让请求扎堆。几个实用手段:
- 客户端限速:在发请求前用令牌桶或信号量限制并发,把 RPM 控制在配额的 80% 以内,主动留出余量。
- 分级路由:简单任务交给 Claude Haiku 4.5,复杂任务才上 Claude Opus 4.8,分摊到不同模型的配额上。选型可参考 Claude 模型怎么选?Opus / Sonnet / Haiku 选型指南。
- 压缩输入:ITPM 撞墙时,先精简系统提示词和历史上下文,多轮对话尤其要做截断,见 Claude API 多轮对话怎么实现?上下文管理详解。
- 错峰与队列:非实时任务放进队列异步消费,避开流量高峰。
- 申请提额:稳定有量后,到 Anthropic 控制台申请提升 Usage Tier,具体流程与额度以 Anthropic 官网为准。
常见问题
429 和 overloaded_error(529)有什么区别?
429 是你自己超出了组织配额,属于客户端侧限流,靠退避重试和降峰解决;529(overloaded_error)是 Anthropic 服务端整体过载,与你的配额无关,同样建议指数退避后重试,但无法靠提额解决,通常等待片刻即可恢复。
用了流式输出(SSE)还会触发 429 吗?
会。流式输出只是改变响应的返回方式,不改变计量规则,输入和输出 Token 一样计入 ITPM/OTPM。流式实现细节见 Claude API 流式输出 Python 实现教程(SSE 详解)。
重试多少次合适?会不会越重试越糟?
一般 3 到 5 次封顶足够。务必加抖动并设等待上限,否则大量客户端同时重试会形成"重试风暴",反而把限流拖得更久。结合客户端主动限速,才能从根本上减少 429 的发生。