OpenRouter 免费层速率限制怎么应对:触发条件与降级策略

2026-08-31

数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。

OpenRouter 官方文档把限制分成两类:一类管你能花多少(credit limits,看账户余额与单 key 消费上限),一类管你能发多少请求(rate limits,管的是免费模型的请求上限和 Cloudflare 的 DDoS 防护)。免费层撞到的是后者,而且免费变体的每分钟请求数与每日请求数是按「累计购买过多少额度」分档的——所以「一个新号从来没花过钱」本身就是限额最紧的那一档。应对顺序也很清楚:先看响应头——官方说明的是,OpenRouter 因平台限制返回错误时会带上这几个头,平台发的就退避加换模型分摊,上游发的就靠 models 模型回退或者放宽供应商路由偏好。多注册几个账号、多建几把 key 是没用的,官方文档里专门有一条提醒说容量是全局治理的。

先分清你撞的是哪一类闸

官方 Limits 页开头给了一张对照表,把两类限制的「管什么、超了报什么、去哪儿查」并排列出来:

  • Credit limits:管的是消费额度,来源有两处——账户余额,以及单把 API key 上可选的消费上限。查的地方是 GET /api/v1/key 响应里的 limit_remaining
  • Rate limits:管的是请求次数,具体包括免费模型的请求上限和 DDoS 防护。查的地方是错误响应上的 X-RateLimit-* 头。

这两类对应的具体状态码本文不写;但官方明确写了额度不足这一类需要充值、触发速率限制这一类要做指数退避重试。分清它俩很重要,因为处理方式完全相反:额度问题靠充值和调高 key 上限解决,等多久都不会自己好;限流问题官方形容为 transient(瞬时的),等一等再重试才是对的路子。

还有一条容易被算到「限流」头上的:官方在 Credit limits 一节写,如果账户额度余额为负,你可能会看到错误,包括对免费模型的请求,把余额补到零以上就能重新使用这些模型。注意官方用的是 may 而不是 will,它给的是一种可能性;也注意这条说明的是负余额会波及免费模型,跟你今天发了多少次请求没有关系。跑免费模型跑着跑着突然全线失败,先去看余额是不是负的,别一头扎进退避逻辑里调参数。

免费层的触发条件:分档,且档位由历史付费决定

官方在 Rate limits 一节列的第一条就是 Free usage limits:如果你用的是免费模型变体(模型 ID 以免费后缀结尾,也就是 Free Variant 章节说的在任意模型 ID 后追加 :free),就会落进一张按「累计购买额度」分档的表。这张表有两列,一列是每分钟请求数,一列是每日请求数。

具体数值在官方这份导出里是空的,我不去别处找数字补,你要用的时候直接看官方限额页。但表的结构本身就说明了三件事

  1. 免费层的闸有两道,分钟级和天级各一道。分钟级那道是抖动型的,你并发一高就撞;天级那道按天计。官方没有说明日限额何时重置、触顶后当天是否彻底不可用,所以写重试逻辑时别对天级闸门做无依据的假设。
  2. 档位的自变量是累计购买额度(all time),不是当月消费、也不是账户余额。官方在 429 的处理建议里也照应了这一点,说在免费变体上可以通过购买一定量的额度来提高每日上限。所以一个从没充过值的号,天生就在最紧的那一档。
  3. 分档只作用在免费变体上。官方同一条建议里给的另一个选项是切到该模型的付费变体,理由写得很直白:付费变体没有平台级的请求上限

第二条限制是 DDoS 防护:官方说 Cloudflare 的 DDoS 防护会拦截「显著超出合理用量」的请求。这条没有量化口径,属于你自己压测压出问题的时候才会遇到的东西。

怎么确认自己确实撞了限流

429 的错误体官方给了完整形状,error.code 是 429,message 是 Rate limit exceeded,metadata.error_typerate_limit_exceeded。程序里应该 switch 的是 error_type 这个字段——官方专门说明这是一个 canonical(规范化的)类型码,跨接口稳定,比只看 HTTP 状态码更适合用来分类处理。

响应头这一块有个反直觉的设计,我第一次读的时候也愣了一下:成功的推理响应里不带 X-RateLimit-*。只有当 OpenRouter 自己因为平台限额返回错误时,错误响应上才会带 X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset 这三个头,描述你撞上的是哪一道闸。另外,当所有尝试过的供应商都返回了重试提示时,错误响应还会带 Retry-After 头。

这个设计的直接后果是:你没法靠响应头做事前监控,因为平时的成功响应压根不给你这个信息。官方给的事前监控办法是主动调 GET /api/v1/key。这个接口返回的字段挺值得逐个认一下:

  • limit / limit_reset / limit_remaining:单 key 的消费上限、重置方式、剩余量。官方对三个字段的 null 语义描述并不相同,具体以官方注释为准。
  • usageusage_dailyusage_weeklyusage_monthly:累计用量,以及当前 UTC 日、当前 UTC 周(从周一起算)、当前 UTC 月的用量。注意口径是 UTC,你按北京时间画的日消耗曲线跟它对不齐是正常的。
  • byok_usage 系列:外部 BYOK 用量的同款四个口径;include_byok_in_limit 决定要不要把它算进消费上限。
  • is_free_tier:官方注释写的是「用户此前是否付费购买过额度」。官方未进一步说明取值含义,也没有把它与限额分档关联起来,别拿它当档位判据
  • 响应里还有一个 rate_limit 对象,官方明确标注它已废弃、可以安全忽略。别去读它。

429 的两个来源,降级路径不一样

官方把 429 的来源拆成了两处,这是决定降级策略的分岔口:

一是 OpenRouter 平台,也就是你撞了上面那些平台限额(免费模型的每分钟或每日请求数,或者 DDoS 防护)。

二是上游供应商,即实际承接你这次请求的那家在限流或已满载。这种情况下,error.metadata.provider_code 会带上供应商的原始错误码(在可获得时);而且官方说明 fallback routing 会先自动为同一个模型重试其他供应商,都试过了错误才会到你手里。换句话说,你看到的供应商侧 429,已经是 OpenRouter 重试过一轮之后的结果了,你在客户端再堆一层立即重试,多半只是重复撞同一堵墙。

按来源,官方给的处置分别是:

  • 指数退避重试。官方的原话是限流是瞬时的,应该等一会儿再重试而不是立刻重发,并且要在 Retry-After 头存在时遵守它。
  • 免费变体上:购买额度以提高每日上限,或者切到该模型的付费变体(付费变体没有平台级请求上限)。
  • 供应商侧的限流:加 fallback models,或者放宽供应商路由偏好,让更多供应商有资格承接这次请求。

最后这条值得展开一句。provider 对象里的 allow_fallbacks 默认就是 true,含义是主供应商不可用时允许换用备用供应商。如果你为了某些原因把它设成了 false,等于主动关掉了这层自动兜底。同理,provider.only 是把候选池限死在给定的供应商列表里——路由能挑的池子越窄,撞上「这家正好在限流」的概率就越高。

模型回退:把降级写进请求里

比在客户端手写重试更省事的一条路,是用 models 参数。官方的说法是提供一个按优先级排列的模型 ID 数组,第一个模型返回错误时,OpenRouter 会自动尝试列表里的下一个。

这里有几处细节值得记住:

  • 默认任何错误都能触发回退,官方列举的包括上下文长度校验错误、被过滤模型的审核标记、限流、以及服务中断。也就是说限流本来就在触发清单里。
  • 计费按最终实际使用的那个模型算,实际用的是哪个会在响应体的 model 字段里返回。所以如果你把一个付费模型排在免费模型后面做兜底,回退发生时的花销是按那个付费模型算的——这不是坏事,但你得知道,别指望在免费模型后面挂一串付费模型还能维持零花销。
  • 如果兜底模型本身也挂了或者报错,官方说 OpenRouter 会把那个错误返回给你。回退不是无限的。
  • 走 Anthropic Messages 接口的话,对应参数叫 fallbacks,形状与 Anthropic SDK 一致,映射到同一套 models 路由;官方特别注明这是 OpenRouter 自己做的回退路由,不走 Anthropic 服务端的回退功能。这个参数每条只接受 model 字段,与 models 参数不能同时用,条数也有上限,超了都会拿到 400,具体约束以官方文档当前版本为准。

如果你连挑模型都懒得挑,官方还有个 openrouter/free 免费模型路由器:它会先按你这次请求需要的能力(比如图像理解、工具调用、结构化输出)过滤可用的免费模型,再从过滤后的池子里随机选一个,响应的 model 字段告诉你实际用了哪个。它的局限官方自己也写了:你无法控制选中哪个模型(想指定就用 :free 变体),免费模型的可用性会变化,而且官方文档在限制一节里提到免费模型的速率限制可能低于付费模型、高峰期延迟可能更高。这些都是官方文档的说法,不是我们跑出来的结论。

流式请求里,限流藏在 200 里

这是免费层最容易踩空的地方。官方说明:如果限流是在流式输出已经开始之后才触发的,错误不会以 HTTP 状态码的形式出现,因为响应头早就发出去了,HTTP 状态仍然是 200 OK。它会变成一个 SSE 事件送达,错误对象出现在事件的顶层(和 idmodelprovider 这些字段并列),同时带一个 choices 数组,其中 finish_reason"error",用来正常终结这条流。发完这个事件,流就结束了。

这意味着只按 HTTP 状态码判断成败的客户端,会把一次被限流打断的生成当成成功——拿到半截内容,还不报错。正确的做法是在流式解析里显式检查每个 chunk 的 choices[0].finish_reason 是不是 error,以及顶层有没有 error 字段。官方文档里给出了 TypeScript 和 Python 两种写法的判断分支,形态就是这么判的。

顺带提一句:官方还写了在 500 类错误上,error.message 会被替换成一个通用字符串、provider_code 会被省略,以防泄漏上游细节。所以流式中途拿到 5xx 时看不到具体原因,不是你解析错了。

别在这三件事上浪费时间

第一,多开号、多开 key 不解决限流。 官方在 Limits 页顶部的提示框里写得很明确:创建更多账号或 API key 不会改变你的速率限制,因为容量是全局治理的。同一段紧接着给了真正有效的做法——不同模型有不同的速率限制,所以可以通过分散到不同模型来分摊负载。这条提示的前半句和后半句要一起读:换 key 没用,换模型有用。

第二,别把 402 当 429 治。 额度不足是消费闸,重试一万次也不会通过;对应的处理顺序是充值把余额补到正、检查 key 上的 limit_remaining 是否耗尽(必要时提高上限或等 limit_reset)、以及提前用 GET /api/v1/key 做监控而不是等请求开始失败。这套顺序官方在 Handling 402 errors 一节里是列成三条给出的。

第三,别拿别人的限额当自己的。 免费变体的档位跟累计购买额度绑定,别人贴出来的可用频率跟你不一定是同一档;而且官方那张表的具体数值本来就随时可能调整,值得记住的是分档这个结构,不是某个瞬时数值。

想再往上一层看限流这件事的通用形态,可以读 各家 API 的 RPM 与 TPM 限流机制429 错误的通用处理思路;只想把 OpenRouter 这一家的 429 排查完,看 OpenRouter 429 触发了怎么办;想搞清楚免费档到底能撑住哪些场景、什么时候必须换付费档,看 OpenRouter 免费模型能用到什么程度

一条可以直接抄的应对顺序

把上面的东西压成一条决策链:请求失败 → 看 error.metadata.error_type 是不是 rate_limit_exceeded(不是的话先按 402 或鉴权类去查)→ 是的话看错误响应上的 X-RateLimit-* 头判断撞的是哪道闸、有没有 Retry-After → 有就按它等,没有就指数退避 → 如果反复撞的是免费变体的天级闸,退避救不了,改走 models 模型回退或换到限额不同的另一个模型 → 长期方案是评估要不要切付费变体(它没有平台级请求上限)。流式场景在这条链之前多加一步:先确认你的解析器真的在检查 finish_reason: "error",否则你连自己被限流了都不知道。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。

留言讨论

评论发布后会被人工复核,违规内容将被删除。

    还没有人评论,来说说你的看法

    如果发表没有反应,可以前往联系我们告诉我们。

    OpenRouter 充值不方便?

    国内直连的 OpenAI 兼容端点,一期提供 DeepSeek,注册送 ¥5。

    看替代方案

    这个页面有问题?

    提交时会附带当前页面地址和浏览器信息,帮助我们定位问题。不填联系方式即为匿名。