AnyRouter Claude Code 验证机制分析
本文档记录了通过逐步删减请求字段、实际发送请求测试,得出的 AnyRouter 对 Claude Code 请求的验证机制。
测试日期:2026-03-16 起,持续追加
测试方法:以完整的 Claude CLI 请求为基准,逐个移除字段并观察响应状态码(200 = 通过,500 = 拒绝)
重要提醒:验证机制具有时变性与灰度特征
AnyRouter 的验证逻辑经过多次反复调整,任何结论都不应被视为长期稳定:
- 请求头校验可能被启用或取消(如
anthropic-beta从"可选"变为"必需") - 白名单策略可能被启用或撤销(如
session_id白名单上线又下线) user_id格式曾整体变更(扁平字符串 → JSON 字符串)- 同一时段内不同 Key 行为可能差异巨大(被封禁/限流的 Key 返回 520/503,正常 Key 返回 200)
- 不同模型的上游可用性独立变化(旧模型下线、新模型灰度上线)
- 部分校验存在灰度/后端负载相关的不稳定行为
使用建议:
- 代理实现应默认携带"完整最小必需集"(见后文),而非依赖某次测试得出的"可省略"结论
- 遇到非预期错误码时,优先换 Key / 换模型 / 换时间重试,再排查请求体
- 本文档中旧结论凡被推翻的,均以「已失效 / 已变更」标注并保留,用于回溯演变轨迹
一、验证结论总览
AnyRouter 的验证只检查请求体,不检查请求头。核心验证点仅有两个:
system数组中必须包含精确的 Claude Code system promptmetadata.user_id必须符合特定格式
2026-04 更新:以上结论为早期测试结果。当前 AnyRouter 同时校验请求头,
缺少必需的anthropic-beta头(尤其是context-1m-2025-08-07标志)会直接返回 400。
详见下方「请求头新增校验」章节。
最小可通过请求 = 标准 Anthropic 请求
+ system[0].text = "You are Claude Code, Anthropic's official CLI for Claude."
+ metadata.user_id = "user_{64位hex}_account__session_{UUID格式}"
补充:请求头新增校验(2026-04-11 确认)
400 错误:“1m 上下文已经全量可用,请启用 1m 上下文后重试”
错误现象:
{"error":"1m 上下文已经全量可用,请启用 1m 上下文后重试","type":"error"}
所有模型、所有 Key 均返回 HTTP 400,与请求体内容无关。
根本原因:
anthropic-beta 请求头中缺少 context-1m-2025-08-07 标志。AnyRouter 现在会检查此 beta flag 来确认客户端已启用 1M 上下文窗口。
解决方案:
在请求头中添加 anthropic-beta,至少包含 context-1m-2025-08-07:
anthropic-beta: context-1m-2025-08-07
Claude Code CLI 2.1.92 实际发送的完整 anthropic-beta 值(共 9 个 flag):
claude-code-20250219,context-1m-2025-08-07,interleaved-thinking-2025-05-14,redact-thinking-2026-02-12,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,fast-mode-2026-02-01
各 flag 含义:
Flag 用途claude-code-20250219
Claude Code 专属标识
context-1m-2025-08-07
启用 1M 上下文窗口(AnyRouter 必须校验项)
interleaved-thinking-2025-05-14
交错思考模式
redact-thinking-2026-02-12
思考内容脱敏
context-management-2025-06-27
上下文管理
prompt-caching-scope-2026-01-05
提示缓存作用域
advanced-tool-use-2025-11-20
高级工具使用
effort-2025-11-24
输出努力程度控制
fast-mode-2026-02-01
快速模式
经逐项省略测试确认,anthropic-beta 是唯一必需的非标准头,其余头(User-Agent、x-app、X-Stainless-*、anthropic-version 等)均可省略。完整测试结果见下方第二章。
测试对比:
anthropic-beta 中包含context-1m-2025-08-07
状态码
否
400(上述错误)
是
200 或 503(验证通过)
二、请求头测试详情
旧测试结果(2026-03-16,已过时) (点击了解更多详细信息)注意:以下为 2026-03-16 的旧测试结果,当时 AnyRouter 不校验请求头。
2026-04-11 重新测试发现anthropic-beta已变为必需头,详见下方更新。
请求头结论(2026-04-11 更新)
AnyRouter 现在校验 anthropic-beta 请求头。 缺少此头或其中不含 context-1m-2025-08-07 会返回 400。
逐项省略测试方法:以完整请求头为基准,每次仅移除一个字段,发送请求并记录响应状态码(自动重试 520)。每个字段测试 2 次有效结果。
移除的请求头 结果 结论Accept
200, 200
可省略
User-Agent
200, 200
可省略
X-Claude-Code-Session-Id
520, 200
可省略
X-Stainless-Arch
200, 200
可省略
X-Stainless-Lang
200, 200
可省略
X-Stainless-OS
200, 200
可省略
X-Stainless-Package-Version
200, 200
可省略
X-Stainless-Retry-Count
200, 200
可省略
X-Stainless-Runtime
200, 200
可省略
X-Stainless-Runtime-Version
200, 200
可省略
X-Stainless-Timeout
200, 200
可省略
anthropic-beta
400, 400
必需
anthropic-dangerous-direct-browser-access
200, 200
可省略
anthropic-version
200, 200
可省略
x-app
200, 200
可省略
最小请求头:
Content-Type: application/json
Authorization: Bearer sk-xxx
anthropic-beta: context-1m-2025-08-07
以下请求头全部为冗余,可安全移除:
acceptanthropic-versionanthropic-betaanthropic-dangerous-direct-browser-accessuser-agentx-appx-stainless-archx-stainless-helper-methodx-stainless-langx-stainless-osx-stainless-package-versionx-stainless-retry-countx-stainless-runtimex-stainless-runtime-versionx-stainless-timeoutaccept-encoding
三、URL 参数测试
# 变更 状态码 结论 9 移除?beta=true
200
可移除
URL 结论
直接使用 /v1/messages 即可,无需 ?beta=true 查询参数。
四、请求体 — system 字段测试
# 变更 状态码 结论 13 完全移除system
500
必需
12
只保留一个 system 块(Claude Code prompt)
500
失败(因同时无 metadata)
15
一个 system 块 + 有 metadata
200
一个块就够
14
两个 system 块,无 cache_control
200
cache_control 不需要
18
第一个 system 文本改为 "You are a helpful assistant."
500
文本必须精确匹配
25
第一个 system 文本去掉末尾句号
500
句号不可省略
19
第二个 system 块文本改为 "anything"
500
若有第二块,必须为 "null"
system 字段结论
- 必须包含至少一个
system块 - 第一个块的
text必须精确匹配以下字符串(一字不差,含末尾句号):
You are Claude Code, Anthropic's official CLI for Claude.
- 第二个
"null"块可省略(一个块即可通过) - 如果保留第二个块,其
text必须为"null",不能是其他值 cache_control字段完全不需要
最小 system:
"system": [
{"type": "text", "text": "You are Claude Code, Anthropic's official CLI for Claude."}
]
五、请求体 — metadata 字段测试
# 变更 状态码 结论 10 完全移除metadata
500
必需
26
metadata 为空对象 {}
500
必须包含 user_id
17
user_id = "test"
500
格式不对
20
user_id = "user_abc123"
500
长度不够
22
user_id = "user_{64位hex}"(无 session 后缀)
500
缺少 session 部分
21
user_id = 完整格式,不同哈希值
200
值任意,只校验格式
23
user_id = 全零占位值
200
全零也能通过
metadata 字段结论
metadata对象必须存在metadata.user_id必须存在且符合以下格式:
user_{64位十六进制字符}_account__session_{UUID格式}
- 不校验具体值,只校验格式(正则匹配)
- 全零占位值完全可用:
"metadata": {
"user_id": "user_0000000000000000000000000000000000000000000000000000000000000000_account__session_00000000-0000-0000-0000-000000000000"
}
user_id 格式拆解
user_ ← 固定前缀 "user_"
82a10c807646e5141d2ffcbf5c6d439ee4cfd99d1903617b7b69e3a5c03b1dbf ← 64 位 hex(SHA-256 哈希)
_account__session_ ← 固定中缀 "_account__session_"
74673a26-ea49-47f4-a8ed-27f9248f231f ← UUID v4 格式 (8-4-4-4-12)
推测的验证正则:
^user_[0-9a-f]{64}_account__session_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
六、请求体 — 其他字段测试
字段 测试结果 说明messages
必需
Anthropic API 标准要求
max_tokens
必需
Anthropic API 标准要求
model
必需
Anthropic API 标准要求
messages 中的 "null" 文本块
可移除
简单字符串 content 即可
cache_control(system 和 messages 上的)
可移除
不参与验证
thinking
可选
只影响是否启用思考链
七、最终最小请求模板
curl https://anyrouter.top/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: sk-xxx" \
-d '{
"model": "claude-opus-4-6",
"messages": [
{"role": "user", "content": "Hello"}
],
"system": [
{"type": "text", "text": "You are Claude Code, Anthropic'\''s official CLI for Claude."}
],
"metadata": {
"user_id": "user_0000000000000000000000000000000000000000000000000000000000000000_account__session_00000000-0000-0000-0000-000000000000"
},
"max_tokens": 1024
}'
八、验证机制推测
根据测试结果,AnyRouter 的验证逻辑推测如下:
收到请求
│
├─ 提取 x-api-key 或 Authorization → 标准认证
│
├─ 解析 JSON body
│
├─ 检查 system[0].text
│ ├─ == "You are Claude Code, Anthropic's official CLI for Claude." → 继续
│ └─ 不匹配或不存在 → 拒绝 (500)
│
├─ 检查 metadata.user_id 格式
│ ├─ 匹配 user_{64hex}_account__session_{UUID} → 继续
│ └─ 格式不对或不存在 → 拒绝 (500)
│
├─ (可选) 如有 system[1],检查 text == "null"
│
└─ 转发到上游 Anthropic API → 返回响应
2026-03-20 补充:固定 user_id 被封禁
使用写死的 user_82a10c... 值持续请求后,该 user_id 被 AnyRouter 封禁,所有携带该值的请求返回 403(空响应体)。换用全零 user_id 或随机生成的值即可恢复。
结论:AnyRouter 虽然不校验 user_id 的具体内容,但会对高频使用的固定 user_id 做封禁处理。代理应每次请求随机生成 user_id。
2026-03-28 补充:metadata.user_id 格式变更 & session_id 校验
格式变更metadata.user_id 的格式已从旧的扁平字符串格式变更为 JSON 字符串格式:
旧格式(已失效,返回 503):
user_{64位hex}_account__session_{UUID}
新格式(当前生效):
"{\"device_id\":\"82a10c807646e5141d2ffcbf5c6d439ee4cfd99d1903617b7b69e3a5c03b1dbf\",\"account_uuid\":\"\",\"session_id\":\"f81a44fc-edfb-40f5-bdd4-f6fd4afbc27c\"}"
字段说明:
device_id:64 位十六进制字符串(SHA-256 哈希)account_uuid:可为空字符串session_id:UUID v4 格式,与请求头X-Claude-Code-Session-Id的值一致
X-Claude-Code-Session-Id 请求头
user_id 中的 session_id
状态码
结论
1
随机 UUID 51ef0c33-...
同一随机值
503
拒绝
2
f81a44fc-edfb-40f5-bdd4-f6fd4afbc27c
同一值
200
通过
结论
- AnyRouter 校验
session_id的具体值(已于 2026-03-30 变更,见下方补充) - 请求头
X-Claude-Code-Session-Id与metadata.user_id中的session_id应保持一致
device_id
session_id
状态码
结论
1
随机值
合法固定值 f81a44fc-...
200
device_id 不参与校验
2
合法固定值 82a10c...
随机 UUID
503
session_id 必须合法
3
随机值
随机 UUID
503
同上
2026-03-30 补充:session_id 白名单校验已取消
2026-03-28 确认的 f81a44fc-edfb-40f5-bdd4-f6fd4afbc27c 白名单值一度失效(503),
但 2026-03-30 测试发现 AnyRouter 已取消 session_id 白名单校验,随机 UUID 全部通过:
session_id
状态码
1
28ea2f67-e043-4107-ae5f-cec919bfaa0c(随机)
200
2
67408c8f-96ee-4a6c-91a1-b21683aceb3f(随机)
200
3
0b9ce4f8-f337-4178-901f-fd9dd818acf8(随机)
200
4
ee785666-9dda-47cb-b49b-445da13cf2a9(随机)
200
5
9444af14-00d2-45a7-a806-dd4cff63f741(随机)
200
6
f81a44fc-edfb-40f5-bdd4-f6fd4afbc27c(旧值)
200
结论:
device_id和session_id均可每次请求随机生成metadata.user_id仍须为 JSON 字符串格式(含device_id、account_uuid、session_id三个字段)- AnyRouter 的验证现在回归到仅校验格式,不校验具体值
设计意图推测
AnyRouter 通过检查 Claude Code 特有的 system prompt 和 metadata 格式来识别"Claude Code 请求",
据此可能提供差异化的路由策略、计费方式或配额管理。验证策略经历了多次变化:
- 早期:旧格式
user_{64hex}_account__session_{UUID},仅校验格式 - 2026-03-28:新 JSON 格式
user_id,一度校验session_id白名单 - 2026-03-30:取消白名单,回归仅校验格式
- 2026-04-09:部分端点/时段出现
session_id校验回归——随机 session_id 返回 503,使用已验证的固定 session_id 可返回 200。此行为不稳定,可能取决于后端负载或灰度策略。建议代理服务默认使用固定 session_id 以提高成功率。
九、503 请求体验证 — thinking block signature 校验(2026-04-15 确认)
问题背景
一份包含 54 条消息的长对话请求体始终返回 503,而一份仅 2 条消息的新对话请求体正常返回 200。通过系统性排查定位到根因。
根因结论
assistant 消息中 thinking block 的 signature 字段为空时,触发 503。
503 请求体的 msg[46](assistant 角色)包含一个 thinking block,其 signature 值为空字符串(长度=0)。这是导致 503 的唯一根因。
该请求体中所有 thinking block 的 signature 状态:
消息 signature 长度 状态 msg[2] 476所有有效 signature 的 thinking block 均未触发 503;唯一空 signature 的 msg[46] 是故障点。
验证证据
关键对照表 测试场景 结果 thinking + 空 signature("")
对原始请求体逐步截取前 N 条消息发送,确认 503 在 msg[46](即 N=46)处首次以 user 结尾仍返回 503:
N=28~45: user 结尾 → 200, assistant 结尾 → 503(API 标准规则)
N=46: assistant 结尾 → 503
N=47: assistant 结尾 → 503(含空 signature thinking)
N=48: user 结尾 → ❌ 503(首次出现 user 结尾也 503)
N=48~54: 全部 503(无论末尾角色)
N=48 以 user 结尾却 503,因为 msg[46] 的空 signature thinking block 已包含在内。
修复验证删除 msg[46] 中的 thinking block(或删除所有空 signature 的 thinking block)后,完整 54 条消息恢复 200:
✅ msg[0:54] 删除空 signature 的 thinking → HTTP 200
回复: 让我先看看之前是否已经有部分输出了。
已排除因素
以下因素经过系统性测试,确认与 503 无关:
可疑因素 测试方法 结果call_ 前缀的 tool_use ID
替换为 toolu_ 前缀
仍 503
缺失 caller 字段
补全 caller: {"type": "direct"}
仍 503
call_ 前缀 + caller 同时修复
替换前缀 + 补全字段
仍 503
WebSearch 工具(503 有 10 个 tools vs 正常 9 个)
正常请求体 + WebSearch tools
200
请求体大小
缩短 system[2] / tool_result / thinking 内容
仍 503
billing header 差异(cc_version / cch 不同)
互换 system[0]
无影响
is_error: true 的 tool_result
包含/排除均测试
无影响
根因溯源
msg[46]-[50] 同时具备两个来自 OpenAI 兼容后端的特征:
call_前缀的 tool_use ID(OpenAI 格式,非 Claude 原生toolu_前缀)- thinking block 的 signature 为空(OpenAI 兼容代理无法生成 Claude 原生签名)
这表明这些消息来自 OpenAI 兼容代理后端,在格式转换过程中 thinking block 的 signature 被丢弃,导致后续请求被拒绝。
次要发现:messages 以 assistant 结尾触发 503
测试过程中发现,messages 数组以 assistant 角色消息结尾时也会触发 503。这是 Claude API 的标准规则(messages 末尾必须是 user 角色),但经代理后错误码从 400 变为 503。
末尾角色 状态码 说明 user 200 正常 assistant此为独立问题,与 thinking signature 无关。
修复方案
发送请求前,删除所有 signature 为空的 thinking blocks:
for msg in body["messages"]:
if msg["role"] == "assistant":
content = msg.get("content", [])
msg["content"] = [
b for b in content
if not (b.get("type") == "thinking" and not b.get("signature"))
]
如果代理服务需要保留 thinking 内容用于上下文,可改为在转发前将空 signature 替换为占位值,但经测试非空但无效的 signature 同样触发 503,因此删除是最稳妥的方案。
十、模型下线与切换:claude-opus-4-7 上线(2026-04-17 确认)
变更概述
模型 状态claude-opus-4-6
已下线
claude-opus-4-7
已上线(新默认 Opus)
验证方式变化
无变化。 现有验证机制(anthropic-beta 头、system[0].text、metadata.user_id JSON 格式、X-Claude-Code-Session-Id 等)完全复用,仅需把 model 字段改为 claude-opus-4-7。
实测对照表
使用当前最小请求模板(零修改)分别测试:
模型 非流式 流式 响应示例claude-opus-4-6
400
400
{"error":"claude-opus-4-6 已下线,请切换到 claude-opus-4-7 模型"}
claude-opus-4-7
claude-sonnet-4-5
429
—
{"error":"Service Unavailable"}(限流,非验证问题)
opus-4-6 返回的是业务层提示(验证已通过、模型路由拒绝),而非验证失败,可作为"验证机制未变"的旁证。
结论
model字段值:claude-opus-4-6→claude-opus-4-7- 其余请求头、请求体字段、URL 全部保持不变
十一、Key 级别的可用性校验(2026-04-17 确认)
现象
即使请求体、请求头完全相同,不同 Key 的响应可能差异巨大:
Key 状态 非流式响应 流式响应 说明 正常 Key{"error":"Service Unavailable"}
Cloudflare 层包装
实测同一请求模板:
- Key A(耗尽)→ 非流式 5/5 次 520 空响应,流式返回 503 Service Unavailable
- Key B(正常)→ 非流式 3/3 次 200,流式 3/3 次 200 SSE
结论
- AnyRouter 对 Key 本身有独立的可用性校验,与模型版本、请求格式无关
- 520 空响应 / 503 Service Unavailable 很可能是 Key 级别问题,而非验证失败或模型下线
- 排查
520/503时应优先换用另一个 Key 复测,再排查请求体
状态码含义更新
结合历史结论,当前完整状态码含义:
状态码 含义 排查方向 200 验证通过且响应成功 — 400 验证失败(缺anthropic-beta / system 错 / user_id 格式错)或 模型已下线
读取 body 中的 error 提示
403
user_id 固定值被封禁
改为随机生成 user_id
429
限流
降低频率或换 Key
500
(历史)验证失败;现在很少出现
—
503
验证通过但后端不可用 或 Key 不可用(流式模式)
换 Key / 检查 thinking signature 是否为空
520
Cloudflare 上游异常,通常是 Key 不可用(非流式模式)
换 Key 复测
十二、最新最小可用请求模板(2026-04-17)
curl https://anyrouter.top/v1/messages \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-xxx" \
-H "anthropic-beta: claude-code-20250219,context-1m-2025-08-07,interleaved-thinking-2025-05-14,redact-thinking-2026-02-12,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,fast-mode-2026-02-01" \
-H "anthropic-version: 2023-06-01" \
-H "User-Agent: claude-cli/2.1.92 (external, cli)" \
-H "X-Claude-Code-Session-Id: <UUID,与 user_id.session_id 一致>" \
-H "x-app: cli" \
-d '{
"model": "claude-opus-4-7",
"max_tokens": 1024,
"system": [
{"type": "text", "text": "You are Claude Code, Anthropic'\''s official CLI for Claude."}
],
"messages": [
{"role": "user", "content": "Hello"}
],
"metadata": {
"user_id": "{\"device_id\":\"<64hex>\",\"account_uuid\":\"\",\"session_id\":\"<UUID>\"}"
},
"thinking": {"type": "adaptive"},
"output_config": {"effort": "high"},
"speed": "fast"
}'
相比文档第七章的"早期最小模板"(仅
Content-Type+x-api-key+ 旧格式user_id),当前版本新增了多个必需项。早期模板已失效,保留作为历史参考。
演变时间轴
日期 关键变化 2026-03-16 初版测试:仅校验请求体system[0].text + metadata.user_id(旧扁平格式)
2026-03-20
固定 user_id 被封禁(403),需随机生成
2026-03-28
user_id 格式变更为 JSON 字符串;一度引入 session_id 白名单
2026-03-30
session_id 白名单取消,回归仅校验格式
2026-04-09
部分端点/时段 session_id 校验回归(灰度)
2026-04-11
anthropic-beta 头变为必需(必须含 context-1m-2025-08-07)
2026-04-15
thinking block 空 signature 触发 503
2026-04-17
claude-opus-4-6 下线,claude-opus-4-7 上线;Key 级可用性差异显著
2026-04-17
确认 thinking 字段是 opus-4-7 必需项(new-api 后端空指针 panic),output_config、speed 可省略
十三、opus-4-7 请求体字段必需性测试(2026-04-17 确认)
测试背景
代码中 thinking / output_config / speed 三个字段是否都必须携带?针对 claude-opus-4-7 模型,逐个移除测试。
测试方法
以完整请求体为基准,按 7 种组合移除字段,每种测 2 次,观察响应状态码。
测试结果
测试组合 2 次结果 结论 全部保留(基准) 200 / 520*thinking
500 / 500
output_config
200 / 520*
speed
200 / 520*
thinking + output_config
500 / 500
thinking + speed
500 / 500
output_config + speed
200 / 520*
*520 为 Cloudflare 上游偶发错误,与字段无关。
500 panic 错误响应
移除 thinking 后返回的错误:
{
"error": {
"message": "Panic detected, error: runtime error: invalid memory address or nil pointer dereference. Please submit a issue here: https://github.com/Calcium-Ion/new-api",
"type": "new_api_panic"
}
}
结论
字段 必需性 说明thinking
必需
缺失触发 new-api 后端 panic(非验证失败,是后端代码 bug)
output_config
可省略
AnyRouter 不校验
speed
可省略
AnyRouter 不校验
根因分析:AnyRouter 验证层本身不校验这三个字段,500 来自上游 new-api 的空指针 bug —— 后端代码假定 thinking 字段一定存在而未做 nil 判断。这是 AnyRouter 上游实现缺陷而非协议要求。
thinking 字段取值语义
"thinking": {"type": "adaptive"}
类型
含义
{"type":"enabled","budget_tokens":N}
旧版:固定 token 预算
{"type":"adaptive"}
新版(推荐):模型自适应决定思考深度
{"type":"disabled"} 或缺失
不思考(但对 opus-4-7 会触发 panic)
adaptive 让模型根据问题难度自动调节思考量——简单问题少想、复杂问题多想,配合 output_config.effort 的 high/medium/low 共同控制行为。
最小必需请求体(2026-04-17 更新)
{
"model": "claude-opus-4-7",
"max_tokens": 1024,
"system": [
{"type": "text", "text": "You are Claude Code, Anthropic's official CLI for Claude."}
],
"messages": [{"role": "user", "content": "Hello"}],
"metadata": {
"user_id": "{\"device_id\":\"<64hex>\",\"account_uuid\":\"\",\"session_id\":\"<UUID>\"}"
},
"thinking": {"type": "adaptive"}
}
相比第十二章的模板,可安全移除 output_config 和 speed;但不可移除 thinking。
14 个帖子 - 14 位参与者