从OpenRouter迁Crazyrouter:Claude Code三处改动
适合谁看 :已经在用或准备用 Claude Code、Cursor、Cline,正在 OpenRouter 和 Crazyrouter 之间做选择的人。
数据日期 :2026 年 10 月 12 日。模型清单、字段命名、价格都在变,动手前先用文末命令自己拉一遍。
结论先行:两家的端点、认证、状态码完全一致,真正拉开差距的是响应体里那四个字段,以及缓存没命中时谁能告诉你原因。
目录
- 一、先看结论:两边打平的地方在哪
- [二、一眼对比:12 行表格](#二、一眼对比:12 行表格)
- 三、响应体:四个字段
- [四、路由:开源模型一个 ID 落到哪](#四、路由:开源模型一个 ID 落到哪)
- 五、降级与限流:规则写在哪
- 六、账单:十倍差在命中率
- [七、迁移三步 + 最小验证](#七、迁移三步 + 最小验证)
- 八、三个失败模式
- 九、按需求对号入座
- 十、参考与自查命令
一、先看结论:两边打平的地方在哪
把同一条 Claude 请求分别发给 OpenRouter 和 Crazyrouter,两边都回 200。都有 Anthropic Messages 端点,x-api-key 和 Authorization: Bearer 都能用,客户端认证方式一行不用改。
所以牌面是平的,别在"谁兼容 Anthropic"这种问题上纠结------两家都兼容。真正不同的是四处:
| 对比项 | 差异 |
|---|---|
| 响应字段 | 一家归一化成跨厂商命名,一家原样透传 Anthropic |
| 缓存诊断 | 命中数都能看到,没命中的原因只有一家给 |
| 限流与降级 | 一家全局管控、规则写在请求里;一家按 token 计、规则挂在 key 上 |
| 模型池 | 归一化后 372 对 177,交集 77 |
从 OpenRouter 迁过来通常是改三处(base URL、key、模型名),外加三个坑。哪家更适合你取决于需求,第九节按需求列表,不排名次。
二、一眼对比:12 行表格
基线是共通的:OpenAI 兼容端点、Anthropic Messages 端点、多模型一个 key、预付费额度,以及图像、视频、语音这类非文本端点,两家都有。
分歧在这里,数字取自两边公开接口与官方文档,核对日期 2026 年 10 月 12 日:
| 项目 | OpenRouter | Crazyrouter |
|---|---|---|
| 原始条目 / 归一化唯一型号 | 458 / 372 | 177 / 177 |
| 两边交集 | 77 | 77 |
| Anthropic Messages 端点 | 有 | 有(两种认证都返回 200) |
cache_control |
支持 | 支持 |
| 响应字段风格 | 跨厂商归一化 | Anthropic 原生透传 |
| 缓存命中数 | prompt_tokens_details.cached_tokens |
原生字段,5 分钟 / 1 小时分档 |
| 缓存未命中的原因 | 无,只看到 cached_tokens 变 0 |
diagnostics.cache_miss_reason |
| 思考 token 计数 | 归一化进 usage | output_tokens_details.thinking_tokens 单独列出 |
| 降级规则写在 | 请求体或预设(@preset/...) |
API key 上(模型白名单 + 预算) |
| 限流作用域 | 全局管控,多开 key 无效 | 按 token 计,可分流 |
| 多 provider 冗余 | 有,带 Sticky Routing | 无,直供 |
| 数据留存文档 | ZDR、区域内路由、主权云 | 仅见"临时图片保留 48 小时" |
有两行要单独说明。
模型池。 372 对 177 是实打实的差距,而且集中在开放权重长尾:Qwen3 37 对 12、Gemini 23 对 8、DeepSeek 17 对 4。要做多模型横评,或者需要冷门开放权重模型,这一格直接决定选型。
限流阈值。 Crazyrouter 没有公布 RPM、TPM、并发数,也没有 Retry-After 说明,这是短板。OpenRouter 把 402、403、429 各自的管辖范围写清楚了,要照着实现限流策略的话,那边的文档更够用。

图 1:OpenRouter 模型列表页,2026-10-12 截取。Crazyrouter 侧的条目数用 /api/pricing 接口拉取。
三、响应体:四个字段
这是全文最关键的一节,也是"两家都写兼容 Anthropic"这句话最容易骗人的地方。
用 x-api-key 向 Crazyrouter 的 /v1/messages 发一个最小请求,返回里这四个字段,是 OpenAI 兼容格式表达不了的:
| 字段 | 作用 |
|---|---|
cache_creation.ephemeral_5m_input_tokens cache_creation.ephemeral_1h_input_tokens |
缓存写入按 5 分钟 / 1 小时两档分别计数 |
output_tokens_details.thinking_tokens |
思考 token 从输出里单独列出 |
diagnostics.cache_miss_reason |
这次为什么没命中 (实测返回 previous_message_not_found) |
safeguard_results |
安全检查结果 |

图 2:实际执行结果。蓝色标注的四处,是 OpenAI 兼容格式无法表达的字段。
OpenRouter 走的是另一条路,它的缓存文档用这套命名:prompt_tokens_details.cached_tokens(命中读取)、cache_write_tokens(写入缓存)、cache_discount(折扣)。Anthropic 原生的 5 分钟 / 1 小时两档,被合并成一个 cached_tokens。
归一化不是缺陷。 它是聚合器的必然选择,而且有真实好处:代码从 Claude 切到 Gemini 再切到 DeepSeek,解析 usage 的逻辑一行不用改。OpenRouter 还有 Provider Sticky Routing,缓存命中后把后续请求粘在同一个 provider 上保热度。
代价藏在故障时刻:命中率突然掉了,归一化之后你只看到 cached_tokens 变成 0,然后自己猜。原生字段会直接告诉你,这次是前缀被改动、消息没对上,还是过期。
python
# 三个断言,把"静默失败"变成"显式报错"
diag = resp.get("diagnostics") or {}
assert resp["usage"]["output_tokens_details"]["thinking_tokens"] > 0, "thinking 没触发,检查 budget_tokens"
miss = diag.get("cache_miss_reason")
if miss:
print(f"缓存未命中原因: {miss}") # 例:previous_message_not_found
这段断言比看日志有用。尤其第二行------如果 budget_tokens 给小了,接口照样返回 200,只是 thinking_tokens 是 0,不写断言就永远发现不了。
四、路由:开源模型一个 ID 落到哪
闭源模型由厂商或其授权伙伴提供,没有选择余地。开源权重模型谁都能托管,这件事在 OpenRouter 上直接改变你付的钱。
以 GLM-5.3 为例,OpenRouter 曾为它列出 47 个 endpoint,输入价从每百万 token 0.07 到 2.80,其中 30 个标着 fp4、nvfp4 或 fp8 量化。默认路由按价格的平方反比加权,所以一条 z-ai/glm-5.3 请求最可能落到便宜的托管方,而量化端点在某些 prompt 上会掉性能。
要指定托管方,得在请求体里写 provider 对象:
json
{
"model": "z-ai/glm-5.3",
"provider": { "order": ["z-ai"], "allow_fallbacks": false }
}
注意 allow_fallbacks: false 的代价:指定 provider 一旦故障,请求直接失败。
Crazyrouter 是直供,一个模型 ID 一个价,没有 provider 参数可设,也就没有这层竞价与冗余。一边给你最低价和最多选择,另一边省掉每次请求都要管理 provider 偏好的成本。 跑 Claude Code 的人通常只用到一两支模型,这个分岔影响不大;做多模型横评的人,影响很大。
五、降级与限流:规则写在哪
两家都会在首选模型失败时换一个模型重试,区别是规则写在哪,这决定了客户端是否必须知道它的存在。
OpenRouter 写在请求里 :传 models 列表,或者存一个预设、把 @preset/<name> 当模型名发过去;还有 openrouter/auto 自动路由器。两种方式下客户端都得发 OpenRouter 特有的东西。
Crazyrouter 挂在 key 上 :每个 token 单独配模型白名单与预算,未授权的模型返回 model not allowed(403),超预算返回 429 或配额耗尽。客户端继续发原来的模型名,规则在控制台改。
这带来一个实际差别:改不动的客户端(只认固定模型名的工具、不方便重新部署的应用),规则挂在 key 上更省事;需要按请求动态切换的,写在请求里更灵活。
限流的作用域也不一样。OpenRouter 的 Limits 页写得很直白:多开账号或多开 key 不会提高限额,容量全局管控。Crazyrouter 的排障建议把"把流量分散到多个 token"列为解法,说明限流按 token 计,可以分流。

图 3:OpenRouter Limits 页,2026-10-12 截取。
另外记一个坑:403 有两个意思。每个 token 可以配模型白名单,未授权模型返回 model not allowed;余额耗尽也返回 403(insufficient_quota)。排错时先读返回体里的错误码,别按 HTTP 状态猜。
六、账单:十倍差在命中率
先把两边的计价结构分开,因为钱不是从同一个地方扣的。
OpenRouter 在标价上加:Standard 套餐刷卡买额度收 5.5%(加密货币 5%,Business 8%),摊到 token 上就是标价 × 1.055,手续费不退。
Crazyrouter 在标价上打:按模型分组给折扣,折扣直接体现在单价里,没有买额度那一刻的附加费。
按每百万 token(输入 / 输出)算,OpenRouter 含费后的有效价:
| 模型 | 官方标价 | OpenRouter(×1.055) |
|---|---|---|
| Claude Opus 5.5 | 4 / 20 | 4.22 / 21.10 |
| Claude Sonnet 5.5 | 2 / 10 | 2.11 / 10.55 |
| GPT-6.1 Sol | 2 / 10 | 2.11 / 10.55 |
| Gemini 3.8 Flash | 0.75 / 3.75 | 0.79 / 3.96 |
| GLM-5.3 | 1.40 / 4.40 | 1.48 / 4.64 |
Crazyrouter 不适用这张表的算法。2026 年 10 月 13 日的价格页快照里,gpt-6-astra 标的是输入 6.50 / 输出 32.50,官方 10 / 50,低 35%。折扣不能按这个比例外推,逐模型不同。
但这两列都不是账单差异的主项。 缓存计费系数两边相同------按 Anthropic 的规则,写入 1.25 倍、读取 0.1 倍、1 小时 TTL 写入 2 倍。差的是命中率。
算一笔账。模型取 Claude Sonnet 5.5(2 / 10),一轮带 6 万 token 上下文,一天 40 轮,假设 40 轮前缀不变:
text
全程不命中:0.06M × $2 = $0.12 / 轮 40 轮 = $4.80 / 天
全程命中: 首轮写入 0.06M × $2 × 1.25 = $0.15
之后 39 轮 × (0.06M × $2 × 0.1) = $0.468
合计 = $0.618 / 天
差额:$4.18 / 天,30 天约 $125
同样的 token 数,十倍的单价差,全部来自命中没命中。前缀会随对话增长,真实差额小于这个上限;但"掉没掉、为什么掉"这个信息差,不随前缀长度变化。
省下来的钱靠调优,调优的前提是知道原因,而原因只有一边写在响应体里。
七、迁移三步 + 最小验证
- 建 key,在控制台生成,按编码工具选对应的集成文档------Claude Code、Codex CLI、Cursor、Cline、Cherry Studio 各有单独一页。
- 改 base URL :OpenAI 兼容用
https://api.crazyrouter.com/v1,Anthropic 用https://api.crazyrouter.com。 - 改模型名 :去掉
vendor/前缀,版本号的点改连字符。
| OpenRouter ID | Crazyrouter ID |
|---|---|
| anthropic/claude-sonnet-5.5 | claude-sonnet-5-5 |
| anthropic/claude-opus-5.5 | claude-opus-5-5 |
| openai/gpt-6.1-sol | gpt-6.1-sol |
| google/gemini-3.8-flash | gemini-3.8-flash |
| z-ai/glm-5.3 | glm-5.3 |
Claude Code 三个环境变量就够:
bash
export ANTHROPIC_BASE_URL="https://api.crazyrouter.com"
export ANTHROPIC_AUTH_TOKEN="你的密钥"
export ANTHROPIC_MODEL="claude-sonnet-5-5"
最小验证,返回 "content": [{"type":"text","text":"OK"}] 且 "stop_reason": "end_turn" 即通:
bash
curl -s -X POST https://api.crazyrouter.com/v1/messages \
-H "x-api-key: $CRAZYROUTER_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"claude-haiku-5-5","max_tokens":512,
"messages":[{"role":"user","content":"Reply with exactly: OK"}]}'
八、三个失败模式
1. 思考块突然消失,但请求是 200
原因 :budget_tokens 给小了不报错,接口照常返回,thinking_tokens 是 0。同一组参数测四款 Claude,budget_tokens: 128 时 Haiku 没有 thinking 块,改成 1024 才有;并且 claude-sonnet-5-5、claude-opus-4-8 在同样参数下只返回 text,claude-opus-5-5、claude-haiku-5-5 才有。
修法 :budget 设到 1024 以上,在返回体里断言 thinking_tokens > 0,别只看状态码。
2. 明明有这个模型,却返回 403
原因:模型白名单没加,或余额不足,两种都返回 403。
修法 :把模型显式加进 allowlist;排错先读 type / code 字段。
3. 多开 key 的习惯,到这边要改
原因:OpenRouter 容量全局管控,多开 key 不放宽额度;Crazyrouter 按 token 计,拆到多个 token 确实能分摊。
修法:从 OpenRouter 过来的人多开 key 会白忙;反过来迁回去时先改掉这个习惯,否则只是多了一份要管的东西。
九、按需求对号入座
两边都不弱,差别在需求落在哪一列。左边是需求,右边是对应的那一侧,理由各一句:
| 你的需求 | 落在哪一侧 | 理由 |
|---|---|---|
| 多模型横评、开放权重长尾 | OpenRouter | 372 对 177,Qwen3 37 对 12 |
| 代码要在多厂商之间频繁切换 | OpenRouter | 归一化字段,解析逻辑不用改 |
| 要跨 provider 的冗余降级 | OpenRouter | 多供应商自动切换 + Sticky Routing |
| 数据驻留、零留存、主权云 | OpenRouter | ZDR、In-Region、Sovereign AI 文档齐全 |
| 要照着文档实现限流策略 | OpenRouter | 402 / 403 / 429 分工 + in-flight 预算 |
| 模型固定在 Claude 工具链 | Crazyrouter | 原生字段透传,thinking、tool_use 都在 |
| 要查缓存为什么没命中 | Crazyrouter | cache_miss_reason 写在响应体 |
| 想靠多 token 分摊限流 | Crazyrouter | 限流按 token 计,可 split traffic |
| 要 token 级预算、白名单、环境隔离 | Crazyrouter | 现成机制,不用自己包一层 |
| 一个 key 还要调图像、语音 | Crazyrouter | 独立端点,不用换平台 |
先把自己那一行圈出来,再决定要不要改 base URL。方向不对的话,三项改动一样要做,省下的东西却用不上。
十、参考与自查命令
价格和模型清单自己拉最准,两个接口都免密钥:
bash
# 模型条目数
curl -s https://openrouter.ai/api/v1/models | jq '.data | length'
curl -s https://crazyrouter.com/api/pricing | jq '.data | length'
# 跑一次最小请求后,看缓存相关字段长什么样
curl -s -X POST https://api.crazyrouter.com/v1/messages \
-H "x-api-key: $CRAZYROUTER_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"claude-haiku-5-5","max_tokens":256,
"messages":[{"role":"user","content":"ping"}]}' | jq '.usage'
参考文档:
- Crazyrouter 价格与折扣
- OpenRouter Limits 文档:三类限制、402/429 分工、in-flight 预算、多开 key 无效
- OpenRouter Prompt Caching 文档:归一化字段、缓存系数、Sticky Routing
- OpenRouter 公开模型接口:458 条目及其元数据,免 key
- Crazyrouter 文档(Claude Messages):端点、认证、tool use、extended thinking
- Crazyrouter 文档(错误处理):错误码表与重试建议
数据采集于 2026 年 10 月 12 日;实测为真实 API 请求,关键项各复测两次。OpenRouter 一侧的结论来自官方文档与公开接口,未做付费实测。
省下了排查时间的话,点个赞、收个藏。 下一篇把"缓存命中率怎么从 60% 提到 95%"的操作步骤拆开写:前缀怎么写、消息怎么排、哪些改动会让缓存整段失效。