DeepSeek API 401 鉴权链路逐段排查方法
调用 DeepSeek API 时收到 401通常不是单一原因而是鉴权链路中某一环断裂。本文按请求从客户端到服务端的实际路径逐段给出排查方法和最小验证代码。说明本文涉及的具体端点、模型名、请求头格式与错误响应字段均为示例实际行为请以 DeepSeek 官方文档和真实响应为准。第一段先打印完整响应体不要只看状态码401 只说明凭证未被接受具体原因需要看响应内容。不同服务、不同版本的错误体结构可能不同因此第一步是原样打印完整响应体和响应头而不是根据记忆猜测错误分类。import requests resp requests.post( https://api.deepseek.com/chat/completions, # 示例端点以官方文档为准 headers{Authorization: Bearer api_key}, json{model: deepseek-chat, messages: [{role: user, content: hi}]}, ) print(resp.status_code) print(resp.headers) print(resp.text)拿到完整响应体后再对照官方文档判断错误字段含义。如果官方文档没有明确分类就把它当作待验证信息不要自行归纳成确定的产品行为。第二段检查 Authorization 头是否被中间件覆盖这是后端框架中最隐蔽的一类问题。常见场景全局请求拦截器统一设置了Authorization覆盖了业务代码传入的 Key日志脱敏中间件把Bearer前缀截断后回写重试逻辑重新构造请求时丢失了原始头。排查方法在真正发出 HTTP 请求的最后一层打印 headers而不是在业务入口打印。以 Python 为例可以用httpx的 event hooks 在发送前拦截import httpx def log_request(request): print(FINAL HEADERS:, dict(request.headers)) with httpx.Client(event_hooks{request: [log_request]}) as client: client.post(url, headersheaders, jsonpayload)如果这里打印出的Authorization与预期不符问题就在客户端中间件而非服务端。第三段核对 API Key 加载顺序与环境变量多环境部署时Key 的来源可能有多层.env文件、系统环境变量、容器编排注入、配置中心。加载顺序不同会导致实际使用的 Key 与预期不一致。排查清单在应用启动时打印 Key 的前 6 位和后 4 位不要打印完整 Key确认加载的是哪一份检查是否存在多个同名环境变量例如 shell 中已 export 的变量覆盖了.env容器场景下确认env注入发生在进程启动之前确认没有把 Key 误写成Bearer sk-xxx整体存入环境变量导致拼接后变成Bearer Bearer sk-xxx。import os key os.environ.get(DEEPSEEK_API_KEY, ) print(key prefix:, key[:6], suffix:, key[-4:], len:, len(key)) assert not key.startswith(Bearer ), 环境变量中不应包含 Bearer 前缀第四段代理与网关是否丢失 Bearer 前缀经过 Nginx、API Gateway 或企业代理时Authorization头可能被重写或丢弃。典型表现直连成功走代理就 401。验证方法用curl -v直连目标端点确认成功再通过代理地址发起同样请求对比发出的请求头中Authorization是否完整检查代理配置中是否有proxy_set_header Authorization ;之类的清空规则确认代理没有把Bearer前缀当作自定义字段剥离。如果代理层做了鉴权转换需要确认转换后的头仍然符合目标服务要求的格式。具体格式以官方文档为准。第五段核对 Key 与 base_url 的来源是否一致如果你的架构中存在多个 baseurl例如自建网关、多环境配置、区域化部署需要核对当前请求使用的 baseurl 与 Key 是否来自同一套配置来源。注意DeepSeek API 本身是否对 Key 与 Endpoint 做区域或环境绑定当前没有官方一手资料可以确认。因此这里只作为基于读者自有架构的检查项而不是 DeepSeek 的产品行为断言。排查时确认当前请求的 base_url 是从哪个配置项读取的当前 Key 是从哪个环境变量或配置中心读取的两者是否由同一套部署配置注入是否存在测试配置覆盖生产配置的情况。建议在配置中把 base_url 和 Key 作为一组绑定管理而不是分开注入。最小验证脚本当上述分段排查仍无法定位时用一个不依赖任何框架的最小脚本做基线验证import os, httpx key os.environ[DEEPSEEK_API_KEY] base os.environ.get(DEEPSEEK_BASE_URL, https://api.deepseek.com) # 示例以官方文档为准 with httpx.Client(timeout30) as c: r c.post( f{base}/chat/completions, headers{Authorization: fBearer {key}, Content-Type: application/json}, json{model: deepseek-chat, messages: [{role: user, content: ping}]}, ) print(r.status_code) print(r.text)如果这个脚本成功说明 Key 和端点本身可用问题在业务代码的中间件或配置层如果这个脚本也 401则问题在 Key 本身、环境变量或网络出口。排查顺序建议按以下顺序推进避免在错误层面反复尝试打印完整 401 响应体对照官方文档确认错误语义用最小脚本直连验证 Key 与端点在最终发送层打印 headers确认 Authorization 未被覆盖核对 Key 加载来源与格式排除重复 Bearer 前缀对比直连与代理请求头定位网关丢失核对 Key 与 base_url 是否来自同一套配置来源。401 的本质是凭证在到达服务端前被修改、丢失或本身无效。逐段隔离变量比反复更换 Key 更有效。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →