Claude学院

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.typeauthentication_error。如果你看到的是 invalid_request_error(400)、permission_error(403)或 rate_limit_error(429),那就是另一类问题,不在本文范围内。把 request_id 记下来,联系 Anthropic 支持时它能帮助定位请求。

401 最常见的 6 个原因(按出现频率排序)

  1. API Key 拼错或多了空格、换行。从控制台复制时常带上首尾空白,或被编辑器折行。
  2. 根本没传 key。环境变量没生效、变量名拼错(如把 ANTHROPIC_API_KEY 写成 ANTHROPIC_KEY),SDK 拿到的是空字符串。
  3. key 已被吊销或删除。在控制台手动 revoke、轮换后旧 key 失效,或团队成员删掉了它。
  4. 鉴权头写错。手写 HTTP 时把 key 放进了 Authorization: Bearer 而不是 x-api-key,或漏掉了 anthropic-version
  5. 同时设置了 ANTHROPIC_API_KEYANTHROPIC_AUTH_TOKEN。SDK 会把两个头都发出去,服务器直接拒绝。
  6. 用错了环境的 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,而是用 requestsfetch 直接发请求,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 官网为准。

Claude API 开发