OpenAI API 401 invalid api key 排查:一行 cURL 定位到底是哪一步错
简答:改了 Key 仍返回 401?先别继续生成新 Key,直接请求 /v1/models:返回 200,说明这次请求的 Key、Authorization 和官方 Base URL 可以完成鉴权,应转查代码环境;仍返回 401,再核对 Key 是否被删除、撤销、带空格,或与组织、项目和请求端点不匹配。PowerShell 不要把 SecureString 直接赋给环境变量,使用普通字符串或 PowerShell 7.1 及以上的 -MaskInput。
定义:OpenAI API 401 invalid api key 是服务端无法接受当前鉴权凭据的错误,常见原因包括 Key 拼写或格式错误、Key 已删除或撤销、程序读取了旧环境变量,以及 Key 与请求的组织、项目或端点不匹配。
30 秒速查:先用 /v1/models 把问题分成两类
改了 Key 仍返回 401?先别继续生成新 Key。用下面的最小请求绕过 Python、Node.js、VS Code 或自动化工具,先判断当前进程实际使用的 Key 能否完成基础鉴权。本站为第三方指南,非 OpenAI 官方,以其官网为准。
| 裸测结果 | 优先判断 | 下一步 |
|---|---|---|
| HTTP 200 | 这次请求的 Key、Authorization 和官方 Base URL 可以完成鉴权 | 转查代码实际加载的环境变量、SDK 初始化、代理参数和请求头 |
| HTTP 401,掩码不是刚生成的 Key | 程序或终端很可能仍在使用旧 Key | 重启运行进程和 IDE,检查 User、Machine 环境变量,并确认 .env 覆盖策略 |
| HTTP 401,掩码与新 Key 相符 | Key 可能已删除、撤销、带空格,或与组织、项目不匹配 | 检查 Key 所属 Project、Organization、权限和请求端点 |
| HTTP 404 或网关自定义错误 | Base URL、路径或网关路由可能不匹配 | 确认端点是否要求 /v1,并确认 Key 是该端点接受的凭据 |
OpenAI 的官方错误码文档将 401 Invalid Authentication、401 Incorrect API key provided、组织成员资格和 IP 未授权分别列出;余额耗尽则属于 429,而不是 401。
Bash、macOS 或 Linux 可以在当前会话中读取 Key,再请求模型列表:
read -s OPENAI_API_KEYexport OPENAI_API_KEYcurl -i https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"
PowerShell 7.1 及以上可以使用掩码输入。Microsoft PowerShell 文档说明,-MaskInput 返回的是字符串,而 -AsSecureString 返回的是 SecureString,后者不能直接作为环境变量值发送:
$env:OPENAI_API_KEY = Read-Host "OPENAI_API_KEY" -MaskInput$headers = @{ Authorization = "Bearer $env:OPENAI_API_KEY" }Invoke-RestMethod -Method Get -Uri "https://api.openai.com/v1/models" -Headers $headers
如果 PowerShell 版本不支持 -MaskInput,可在私密终端使用普通 Read-Host,但不要把真实 Key 写入命令历史、脚本或截图。上面的 $env: 赋值只对当前 PowerShell 会话生效。
先看 401 响应正文,再决定查 Key 还是查本地环境
401 的响应正文比“请求失败”更有区分度。常见的脱敏示意如下,实际字段和文本应以你的响应为准:
{"error":{"message":"Incorrect API key provided: sk-proj-****abcd.","type":"invalid_request_error","code":"invalid_api_key"}}{"error":{"message":"Invalid Authentication","type":"invalid_request_error"}}
如果错误信息中的前缀和末尾字符仍对应旧 Key,优先排查终端、IDE、任务启动器或服务进程中的旧变量;如果掩码对应新 Key,则继续检查 Key 是否属于当前 Project、组织是否正确、请求是否带入了过时的组织或项目配置。
| 现象 | 它代表什么 | 处理方式 |
|---|---|---|
| HTTP 401,Incorrect API key provided | 服务端认为请求中的 Key 不正确,官方列出的原因包括拼写、额外空格、属于其他组织或项目、已删除或停用,以及本地缓存旧 Key | 比对响应中的掩码、Key 管理页和程序最终发出的值 |
| HTTP 401,Invalid Authentication | 鉴权凭据无效,可能涉及撤销 Key、组织或项目归属、端点权限 | 检查 Authorization、组织 ID、项目 ID、Key 权限和端点 |
Python 启动前出现 The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable | 客户端初始化时没有拿到有效的非空 Key,还没有形成服务端 HTTP 401 | 检查当前进程的 OPENAI_API_KEY,再创建客户端 |
Python 请求后捕获到 AuthenticationError | 官方 Python SDK 将 HTTP 401 映射为 AuthenticationError | 回到 Key、组织、项目和请求头排查 |
400 或 unsupported_parameter | 请求已到达接口,但参数或字段不被当前接口接受 | 按接口文档删除或改正参数,不要继续更换 Key |
官方 Python SDK 的错误类型说明将 401 映射为 AuthenticationError;OpenAI 错误码文档也将权限不足、无效 Key 和错误请求分开说明。
改了 .env 仍报旧 Key:重启进程并检查 Windows 持久变量
.env 文件改变后,已经启动的终端、IDE、开发服务器或后台任务不会自动替换进程环境变量。Python 使用 python-dotenv 时,load_dotenv() 默认也不会覆盖已经存在的同名环境变量;只有在明确需要时才使用 load_dotenv(override=True)。
- 停止正在运行的 Python、Node.js、n8n 或其他调用进程。
- 关闭并重新打开集成终端。如果你通过 Windows 的用户变量、系统变量或
setx修改过 Key,完全退出 VS Code 后再重新启动。 - 只检查变量是否存在、长度和末尾 4 位,不打印完整 Key:
python -c "import os; k=os.getenv('OPENAI_API_KEY',''); print({'exists':bool(k),'length':len(k),'last4':k[-4:] if k else ''})" - 检查当前 PowerShell 会话、用户级和系统级变量:
Get-Item Env:OPENAI_API_KEY -ErrorAction SilentlyContinue、[Environment]::GetEnvironmentVariable('OPENAI_API_KEY','User')、[Environment]::GetEnvironmentVariable('OPENAI_API_KEY','Machine') - Python 项目中,在读取配置的位置明确加载策略:
from dotenv import load_dotenv; load_dotenv(override=True),然后再初始化客户端。 - Node.js 项目要重新启动开发服务器;只刷新浏览器页面不会改变已经运行的 Node 进程环境。
如果响应掩码显示的是旧 Key,说明应继续追踪“哪个进程提供了这个值”,而不是只检查当前目录的 .env。如果当前环境变量长度和末尾 4 位与预期一致,仍要确认代码没有从其他配置文件、密钥管理器或启动脚本读取另一套变量。
sk-proj-、组织和项目配置:先减少变量,再逐项加回
项目级 Key 不能只看前缀。OpenAI 的认证文档和官方 Python SDK 说明了 API Key、组织和项目配置的客户端字段;当前 SDK 会从 OPENAI_API_KEY、OPENAI_ORG_ID 和 OPENAI_PROJECT_ID 等环境变量读取对应配置。
- 确认 Key 是在目标 Project 下创建,而不是另一个 Project 或 Organization。
- 确认代码、环境变量或 SDK 初始化参数中没有残留旧的组织 ID、项目 ID 或自定义请求头。
- 先做最小化测试,只保留正确的
Authorization: Bearer,不要同时带入不确定的组织、项目和网关头。 - 如果最小请求成功,再逐项加回组织、项目和其他请求头;一旦重新出现 401,就比较刚加入的字段。
- 如果 Key 已删除、停用或疑似泄露,创建新 Key 后同步替换本地、CI/CD 和生产环境的值。
官方错误码文档列出的 401 原因包括撤销的 Key、属于其他组织或项目的 Key,以及没有调用目标端点所需权限的 Key。由此可见,账号有余额不能直接证明当前请求使用的凭据有效;余额问题应优先按 429 相关错误排查。
官方 API 与兼容网关:Base URL 和 Key 必须成套
官方 API 的最小验证地址是 https://api.openai.com/v1/models。如果你使用 OpenAI 兼容网关,则必须同时使用该网关要求的 Base URL、Key、模型名和路径;不要把官方 Key、网关地址以及另一套组织或项目头混在一次请求中。
确认鉴权后,再做最小 POST 请求。Bash:
curl -i https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"model":"MODEL_ID","messages":[{"role":"user","content":"ping"}]}'
PowerShell:
$body = @{ model = "MODEL_ID"; messages = @(@{ role = "user"; content = "ping" }) } | ConvertTo-Json -Depth 5Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/chat/completions" -Headers $headers -ContentType "application/json" -Body $body
MODEL_ID 必须替换为该端点实际支持的模型名。模型名错误通常会进入模型或参数错误分支,不应直接判断为 Key 无效。响应中的 x-request-id 只能用于辅助定位请求;透传网关可能保留或转发该响应头,不能单凭它证明请求直接到达官方服务。
修复 401 后的 Key 安全清单
API Key 应保存在服务器端环境变量或密钥管理系统中,不要写入浏览器前端、移动应用、公开仓库、日志或截图。可参考 OpenAI 的账号与 API Key 安全指南。
- 将
.env加入.gitignore,避免真实凭据进入版本库。 - 日志只记录是否存在、长度和末尾少量字符,不记录完整值。
- 怀疑泄露时删除受影响的 Key,并同步更新本地、CI/CD 和生产配置。
- 不同项目使用不同 Key,便于区分用量和撤销范围。
- 保留失败请求的时间、HTTP 状态码和 request ID,排查时不要上传完整 Authorization 头。
不要把“重新生成 Key”当作唯一解法。先通过 /v1/models 分清是服务端凭据问题,还是本地环境、SDK、请求头和 Base URL 问题,通常能减少无效操作。
常见问题
OpenAI API 401 invalid api key 是不是余额不足?
通常不是优先判断项。官方错误码将余额耗尽列为 429 credit_balance_exhausted;401 应先检查 Key 是否正确、是否被删除或撤销,以及组织、项目、权限和请求头是否匹配。
为什么我改了 .env,程序还是使用旧的 OpenAI API Key?
运行中的进程不会自动读取修改后的 .env;系统环境变量也可能优先于 dotenv 文件。重启运行进程和 IDE,检查当前会话、User、Machine 变量,并在 Python 中根据需要使用 load_dotenv(override=True)。
PowerShell 怎么安全地做 401 裸测?
PowerShell 7.1 及以上可使用 $env:OPENAI_API_KEY = Read-Host "OPENAI_API_KEY" -MaskInput,再通过 Invoke-RestMethod 请求 /v1/models。不要使用 -AsSecureString 后直接赋给环境变量,因为它返回 SecureString 对象,而不是可发送的 Key 字符串。
cURL 返回 200,但 Python 代码仍返回 401,说明什么?
通常说明两次请求使用的 Key、Base URL、请求头或进程环境不同。应比较实际 URL、Key 的长度和末尾 4 位、组织项目配置以及 SDK 初始化参数,而不是直接假设同一个 Key 在代码中生效。
sk-proj- 开头的 Key 为什么仍然会 401?
前缀不能证明 Key 属于当前 Project。检查 Key 是否在目标 Project 创建,是否残留错误的 OPENAI_ORG_ID、OPENAI_PROJECT_ID 或自定义请求头,并先用只带 Authorization 的最小请求验证。
看到 x-request-id 响应头,能证明请求直达官方吗?
不能单独证明。兼容网关或透传代理也可能保留或转发该响应头,应结合实际 Base URL、网关文档和响应正文判断请求由哪个端点处理。