Claude API 报错 401 怎么解决?认证失败排查指南
Claude API 返回 401(错误类型 authentication_error)只有一个含义:服务器没能验证你的身份。换句话说,请求里的 API Key 无效、缺失、被吊销,或者鉴权头格式写错了。401 不是限流也不是权限不足(那是 429 和 403),先把方向定准,再按下面的顺序逐项排查,通常几分钟就能修好。
先看清楚 401 长什么样
Claude 的 Messages API(POST /v1/messages)在认证失败时返回的 JSON 大致如下:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
},
"request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}
关键字段是 error.type 为 authentication_error。如果你看到的是 invalid_request_error(400)、permission_error(403)或 rate_limit_error(429),那就是另一类问题,不在本文范围内。把 request_id 记下来,联系 Anthropic 支持时它能帮助定位请求。
401 最常见的 6 个原因(按出现频率排序)
- API Key 拼错或多了空格、换行。从控制台复制时常带上首尾空白,或被编辑器折行。
- 根本没传 key。环境变量没生效、变量名拼错(如把
ANTHROPIC_API_KEY写成ANTHROPIC_KEY),SDK 拿到的是空字符串。 - key 已被吊销或删除。在控制台手动 revoke、轮换后旧 key 失效,或团队成员删掉了它。
- 鉴权头写错。手写 HTTP 时把 key 放进了
Authorization: Bearer而不是x-api-key,或漏掉了anthropic-version。 - 同时设置了
ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN。SDK 会把两个头都发出去,服务器直接拒绝。 - 用错了环境的 key。把测试组织的 key 用到了生产,或反过来;不同 workspace 的 key 不能混用。
第一步:确认 key 本身没问题
不要先怀疑代码,先确认 key 是有效的。用一条最小化的 curl 直接打接口,绕开所有 SDK 和框架:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-haiku-4-5",
"max_tokens": 16,
"messages": [{"role": "user", "content": "ping"}]
}'
这里有三个细节必须对:鉴权头是 x-api-key(不是 Authorization);anthropic-version 是必传头,固定值 2023-06-01;用最便宜的 claude-haiku-4-5 做连通性测试即可。如果 curl 能通而你的程序 401,问题就在程序读取 key 的环节,不是 key 本身。如果 curl 也 401,去控制台确认 key 状态,必要时新建一个。这一步和你申请 Claude API Key时拿到的应当是同一把。
第二步:检查环境变量是否真的传进去了
「没传 key」是 401 里最隐蔽的一类。SDK 默认从环境变量 ANTHROPIC_API_KEY 读取,但环境变量在子进程、容器、systemd 服务、IDE 运行配置里经常丢失。先在代码里打印长度(绝不要打印完整 key)确认它非空:
import os
from anthropic import Anthropic
key = os.environ.get("ANTHROPIC_API_KEY", "")
print("key 是否存在:", bool(key), "长度:", len(key))
print("前缀:", key[:14] if key else "(空)")
client = Anthropic() # 自动读取 ANTHROPIC_API_KEY
resp = client.messages.create(
model="claude-haiku-4-5",
max_tokens=16,
messages=[{"role": "user", "content": "ping"}],
)
print(resp.content[0].text)
Claude 的 key 都以 sk-ant- 开头。如果前缀不对,说明读到的是别的变量或被截断了。Node 端同理:
import Anthropic from "@anthropic-ai/sdk";
console.log("key 长度:", (process.env.ANTHROPIC_API_KEY || "").length);
const client = new Anthropic(); // 自动读取 ANTHROPIC_API_KEY
const resp = await client.messages.create({
model: "claude-haiku-4-5",
max_tokens: 16,
messages: [{ role: "user", content: "ping" }],
});
console.log(resp.content[0].text);
如果你不想依赖环境变量,可以显式传入:Anthropic(api_key="sk-ant-...")(Python)或 new Anthropic({ apiKey: "sk-ant-..." })(Node)。但务必从配置或密钥管理服务读取,不要把 key 硬编码进源码并提交到仓库——一旦泄漏,Anthropic 可能自动吊销该 key,那时你会得到同样的 401。SDK 和 Key 的配置细节可参考 Anthropic Python SDK 安装与配置。
第三步:用 SDK 的类型化异常精准捕获
不要靠匹配错误字符串判断 401,SDK 给每个 HTTP 状态码都提供了专门的异常类,认证失败对应 AuthenticationError:
import anthropic
from anthropic import Anthropic
client = Anthropic()
try:
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=64,
messages=[{"role": "user", "content": "你好"}],
)
print(resp.content[0].text)
except anthropic.AuthenticationError as e:
print("认证失败(401),检查 API Key:", e.status_code, e.type)
except anthropic.APIStatusError as e:
print("其他 API 错误:", e.status_code, e.type)
Node 端用 instanceof 判断,从最具体的异常类查到最宽泛的:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
try {
const resp = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 64,
messages: [{ role: "user", content: "你好" }],
});
console.log(resp.content[0].text);
} catch (err) {
if (err instanceof Anthropic.AuthenticationError) {
console.error("认证失败(401),检查 API Key:", err.status, err.type);
} else if (err instanceof Anthropic.APIError) {
console.error("其他 API 错误:", err.status, err.type);
} else {
throw err;
}
}
手写 HTTP 请求时的鉴权头陷阱
如果你没用官方 SDK,而是用 requests、fetch 直接发请求,401 多半来自鉴权头。Claude API 用的是 x-api-key 头,不是 OpenAI 风格的 Authorization: Bearer。常见错误对照如下:
| 错误写法 | 正确写法 |
|---|---|
Authorization: Bearer sk-ant-... | x-api-key: sk-ant-... |
| 漏掉版本头 | 必须带 anthropic-version: 2023-06-01 |
| 同时设置两种鉴权变量 | 只保留 ANTHROPIC_API_KEY,unset 掉 ANTHROPIC_AUTH_TOKEN |
一个例外:如果你用的是 OAuth 短期令牌(比如通过 ant auth login 登录后拿到的 token),那才需要放在 Authorization: Bearer 上,并额外加 anthropic-beta: oauth-2025-04-20 头。普通 API Key 永远走 x-api-key。从 API Key 切到 OAuth 是一次头部改造,不是简单换个值。整套调用流程可对照 Claude API 从注册到第一次请求这篇逐步走一遍。
401 之外:别把这几种错误当成认证问题
- 403 permission_error:key 有效,但没有访问该模型或功能的权限,去控制台检查组织/workspace 权限。
- 404 not_found_error:模型 ID 拼错,比如写成
claude-sonnet-4.6而正确是claude-sonnet-4-6。 - 429 rate_limit_error:限流,不是认证问题,需要重试策略,见 Claude API 429 限流报错的 3 种重试方案。
把状态码和 error.type 配套看,能避免把权限或限流误判成认证失败而白白折腾 key。
常见问题
curl 能通但 SDK 一直 401,是为什么?
几乎可以肯定是程序没读到 key。curl 用的是当前 shell 的环境变量,而你的程序可能跑在不同的进程、容器或运行配置里,环境变量没被继承。在代码里打印 len(api_key) 确认非空,或显式把 key 传给客户端构造函数,问题立刻现形。
刚轮换了 API Key,新 key 还是报 401?
先确认应用真的加载了新值——很多框架会缓存环境变量,需要重启进程甚至重新部署才会生效。其次检查旧 key 是否还残留在某个配置文件或密钥管理服务里被优先读取。最后,新建的 key 在控制台偶有极短的生效延迟,等一两分钟再重试一次。
本地正常,部署到服务器就 401?
典型的环境差异:本地 .env 里有 key,服务器上忘了配。检查 CI/CD 的密钥注入、容器的环境变量、systemd 服务文件的 Environment= 配置。同时确认服务器用的不是另一个组织或测试 workspace 的 key——具体配额与权限以 Anthropic 官网为准。