调用第三方API服务(New API)被Cloudflare拦截:从User-Agent到请求头的排查与修复
发布时间:2026/10/2 18:18:58 作者:尧图编辑部 阅读量:1,286
被Cloudflare拦截:从User-Agent到请求头的排查与修复)
1. 第三方API被 Cloudflare 拦截的真实场景还原你写了一段 Python用 openai 库去调一个第三方 API 服务New API 面板搭的 OpenAI 兼容接口本地跑得好好的换台机器、换个网络突然就返回一大坨 HTML里面写着Sorry, you have been blocked、Cloudflare Ray ID、Please enable cookies。这不是你的代码写错了也不是 API Key 失效了而是请求在到达 New API 服务之前先被它前面的 Cloudflare 挡下来了。这个场景在第三方 API 接入里非常典型。New API 本身只是一个转发/聚合面板很多部署者会把它挂在自己的域名下而域名为了防刷、防爬、防滥用通常会套一层 Cloudflare。Cloudflare 的默认安全策略里会对「看起来不像正常浏览器」的请求做拦截。Python 的 openai 库、requests 库默认发出的 User-Agent 是OpenAI/Python 1.x.x或者python-requests/2.x.x这种特征在 Cloudflare 眼里就是「脚本流量」命中规则就直接返回 403 拦截页。很多人第一反应是「换 IP」。我试过换了好几个出口 IP结果一样被拦。原因很简单Cloudflare 拦的不是你的 IP 信誉而是你的请求特征。你换 IP 但 User-Agent 还是python-requests特征没变照样命中。所以正确的排查方向不是换 IP而是从 User-Agent、请求头、调用方式三个层面去「伪装成一个正常浏览器」。这篇文章要解决的问题很具体当你的第三方 APINew API被 Cloudflare 拦截时怎么定位、怎么改请求头、怎么用 curl 和代码验证拦截是否解除。适合正在接 OpenAI 兼容接口、被 403 卡住的开发者。核心检索词就是「第三方API New API Cloudflare 拦截 User-Agent 排查修复」下面按步骤拆开讲。先明确一个判断你拿到的响应如果是 HTML 而不是 JSON基本可以确定是网关层拦截而不是 API 业务层报错。正常的 OpenAI 兼容接口报错会返回 JSON比如{error: {message: invalid api key}}。而 Cloudflare 拦截返回的是完整 HTML 页面Content-Type是text/html状态码通常是 403。这个区分很重要它决定了你后面该改代码还是改请求头。2. TaoToken 前置准备拿到可用的 Base URL 与 Key在动手改请求头之前得先有一个稳定的接入点。如果你现在用的第三方 API 域名本身就被 Cloudflare 拦得厉害那再怎么改 User-Agent 也是治标。更稳的做法是换一个专门做 API 聚合、对开发者调用友好的入口。TaoToken 就是这类服务它提供 OpenAI 兼容接口Base URL 固定、请求头要求清晰不会因为你是脚本调用就给你甩一个 Cloudflare 拦截页。接入前你需要准备三样东西Base URL、API Key、Model ID。这三件套是任何 OpenAI 兼容接口的通用配置缺一不可。TaoToken 的 API 地址是https://taotoken.net/api注意这里不带任何多余路径/v1是在调用时拼上去的。API Key 需要你登录后在控制台生成。具体操作路径是这样的先打开官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content注册账号然后进入控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite在 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite创建一个新的 Key。创建时建议给它起个能认出来的名字比如csdn-test方便后面排查是哪个 Key 出的问题。拿到 Key 之后先别急着写代码。我建议你先用最原始的方式验证一下这个 Key 和 Base URL 能不能通也就是用 curl 发一个最小请求。这一步能帮你把「Key 问题」和「请求头问题」分开。如果 curl 直接就能通说明服务端没问题问题出在你的代码请求头如果 curl 也被拦那说明是域名层面的策略需要换入口。这里有个细节要注意TaoToken 的 Base URL 是https://taotoken.net/api你在 openai 库里配置base_url的时候要写成https://taotoken.net/api/v1因为 openai 库会自动在 base_url 后面拼/chat/completions。如果你只写到/api那最终请求会变成/api/chat/completions路径就错了。这个坑很多人踩过报错通常是 404 而不是 403和 Cloudflare 拦截要区分开。Model ID 这块TaoToken 支持多种模型你在控制台或者文档里能看到当前可用的模型列表。调用时model参数填对应的 ID 就行比如gpt-4o-mini这类。如果你不确定用哪个先用一个便宜的模型做连通性测试通了再换你要用的正式模型。这样能避免因为模型名写错导致的报错干扰排查。3. 可复制的请求头配置从 User-Agent 到完整 Headers现在进入核心部分。Cloudflare 拦截脚本流量的判断依据主要是 User-Agent、请求头完整性、以及请求行为特征。我们要做的就是把这三样都「伪装」成正常浏览器。下面给出可直接复制的配置分 Python openai 库、curl、以及配置文件三种形式。先说 Python openai 库的写法。openai 库允许在初始化客户端时传入default_headers这是最干净的改法不用去改底层 requests 的全局配置。代码如下import os from openai import OpenAI client OpenAI( base_urlhttps://taotoken.net/api/v1, api_keyos.getenv(TAOTOKEN_API_KEY), default_headers{ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36, Accept: application/json, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Accept-Encoding: gzip, deflate, br, Connection: keep-alive, }, ) resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: ping}], ) print(resp.choices[0].message.content)这里的关键是User-Agent要写成一个真实的 Chrome 浏览器 UA。注意不要用太老的版本号Cloudflare 对老 UA 也有策略。上面用的是 Chrome 125你可以换成当前较新的版本。Accept和Accept-Language是加分项让请求头看起来更完整。Accept-Encoding里带br表示支持 Brotli 压缩这也是现代浏览器的特征。如果你用的是 requests 库直接调而不是 openai 库那配置方式类似但要注意 requests 的headers参数会覆盖默认头import requests headers { Authorization: Bearer YOUR_TAOTOKEN_KEY, Content-Type: application/json, User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36, Accept: application/json, Accept-Language: zh-CN,zh;q0.9, } resp requests.post( https://taotoken.net/api/v1/chat/completions, headersheaders, json{ model: gpt-4o-mini, messages: [{role: user, content: ping}], }, timeout30, ) print(resp.status_code) print(resp.text[:500])注意Content-Type必须是application/json这是 OpenAI 兼容接口的硬要求。Authorization用Bearer前缀加你的 Key。这两个头是业务层必须的和 Cloudflare 无关但少了会报 401。再说 curl 的写法这是排查时最该先跑的命令curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -H User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 \ -H Accept: application/json \ -d { model: gpt-4o-mini, messages: [{role: user, content: ping}] }curl 默认的 User-Agent 是curl/8.x.x这个在 Cloudflare 眼里也是脚本特征。所以哪怕你用 curl 测试也要手动加上浏览器 UA否则你测出来的「被拦」可能是 curl 自己造成的而不是你的代码问题。如果你用的是 Cline、Claude Code 这类工具配置通常写在 JSON 或 settings 文件里。以 Cline 的 MCP 配置为例Base URL、Key、Model ID 三件套要写全{ mcpServers: { taotoken: { url: https://taotoken.net/api/v1, headers: { Authorization: Bearer YOUR_TAOTOKEN_KEY, User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 }, model: gpt-4o-mini } } }Codex 的auth.json配置也是同理Base URL 写https://taotoken.net/api/v1Key 填进去Model ID 指定清楚。这三个字段任何一个写错都会导致调用失败但报错信息不同Base URL 错通常是 404Key 错是 401Model ID 错是 400 或 404。把这些区分开排查效率会高很多。4. 验证请求与成功结果确认拦截是否解除配置改完之后怎么确认拦截真的解除了不能只看「没报错」要看响应内容。下面给出几个验证动作从简到繁。第一步用 curl 跑上面那段命令观察返回。如果返回的是 JSON里面有choices字段说明通了。如果返回的还是 HTML里面有cf-wrapper或Sorry, you have been blocked说明拦截还在。这时候你要看响应头里的Server字段如果是cloudflare那确认是 CF 层拦截。第二步在 Python 里加一段打印把状态码和响应体前 500 字符打出来resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: ping}], ) print(status ok) print(resp.choices[0].message.content)如果这段能打印出模型返回的内容比如pong或者一段正常回复说明请求头配置生效了。注意 openai 库在遇到 403 时会抛异常异常信息里会带响应体你可以捕获异常打印出来看from openai import APIStatusError try: resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: ping}], ) print(resp.choices[0].message.content) except APIStatusError as e: print(status:, e.status_code) print(body:, e.response.text[:500])这样你能清楚看到是 403 还是 401以及响应体里是不是 Cloudflare 的 HTML。第三步验证稳定性。单次成功不代表稳定Cloudflare 的策略可能是概率性的。建议连续跑 10 次请求统计成功率import time ok 0 for i in range(10): try: resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: fping {i}}], ) ok 1 except Exception as e: print(f第 {i} 次失败:, type(e).__name__) time.sleep(1) print(f成功 {ok}/10)如果 10 次全过说明配置稳定。如果有失败看失败时的异常类型和响应体判断是偶发拦截还是配置问题。偶发拦截通常和请求频率有关可以适当加time.sleep降低频率。第四步如果你用的是 TaoToken 这类入口可以直接在模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite手动发一条消息确认服务本身是通的。如果网页端能通、代码端不通那问题一定在代码的请求头或网络环境不在服务端。这个对照实验能帮你快速缩小范围。成功的结果长这样状态码 200响应体是 JSONchoices[0].message.content有内容usage字段里有 token 统计。如果你看到这些说明 Cloudflare 拦截已经解除请求正常到达了 API 业务层。5. 本篇常见错误排查401、local proxy failed、reading choices排查过程中会遇到几类典型报错这里逐个对照。先说你最可能遇到的 401。401 的响应体通常是{error: {message: invalid api key}}或者Incorrect API key provided。这不是 Cloudflare 拦截是 Key 本身的问题。检查三件事Key 有没有复制完整前后有没有空格、Bearer前缀有没有加、Key 有没有过期或被禁用。如果你在 TaoToken 控制台重新生成过 Key旧 Key 会失效代码里要同步更新。第二类是local proxy failed或者连接超时。这个报错说明请求根本没发出去卡在本地网络层。常见原因是本地配了系统代理但代理不可用或者环境变量HTTP_PROXY、HTTPS_PROXY指向了一个失效的地址。检查方式是打印环境变量import os print(os.environ.get(HTTP_PROXY)) print(os.environ.get(HTTPS_PROXY))如果有值且你不需要代理就清掉unset HTTP_PROXY HTTPS_PROXY。注意这里说的是本地网络配置问题不是让你去用什么特殊网络工具纯粹是排查环境变量污染。第三类是Error reading choices或者list index out of range。这个报错通常发生在你解析响应的时候resp.choices[0]取不到值。原因可能是响应体不是预期的 JSON 结构比如被 Cloudflare 拦截返回了 HTMLopenai 库解析失败或者返回了错误 JSON 但你的代码没判断。正确做法是先判断响应是否正常再取 choicesif resp.choices and len(resp.choices) 0: print(resp.choices[0].message.content) else: print(no choices, raw:, resp)第四类是 OAuth 相关报错比如OAuth token expired或invalid_grant。这类报错出现在你用 Claude Code 或者某些需要 OAuth 授权的工具时。OAuth token 有有效期过期后需要重新授权。如果你用的是 API Key 方式接入 TaoToken就不会遇到 OAuth 问题因为 API Key 不走 OAuth 流程。这也是为什么推荐用 API Key 接入的原因之一少一层授权状态要维护。第五类是model not found或The model does not exist。这是 Model ID 写错了。不同服务商的模型命名不一样有的用gpt-4o有的用gpt-4o-2024-08-06。你要以 TaoToken 文档里列的为准。写错模型名不会触发 Cloudflare 拦截但会返回 404 或 400响应体是 JSON 错误信息和 CF 的 HTML 拦截页很好区分。把这几类报错和 Cloudflare 拦截放在一起对照你会发现一个规律CF 拦截返回 HTML业务报错返回 JSON。记住这个区分排查时先看Content-Type是text/html就往请求头方向查是application/json就往 Key、Model、参数方向查。这个判断能帮你省掉大量试错时间。6. 稳定调用的接入建议与 CTA把请求头配好只是第一步长期稳定调用还需要注意几点。第一User-Agent 不要写死一个太老的版本隔一段时间更新一下保持和主流浏览器版本接近。第二请求频率不要太高Cloudflare 对高频脚本流量有速率限制适当加间隔。第三Key 要保管好不要硬编码在代码里提交到仓库用环境变量或者配置文件管理。如果你现在的第三方 API 域名拦截严重换请求头也压不住那建议直接换一个对开发者友好的入口。TaoToken 的 API 地址是https://taotoken.net/apiBase URL 配https://taotoken.net/api/v1Key 在控制台生成Model ID 按文档填。三件套配齐用上面的 curl 命令先验证连通性通了再写进代码。需要长期跑编码任务或者 Agent 的可以看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite它针对持续调用场景做了优化。只是想先验证模型效果的直接去模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite手动发几条消息确认服务正常再接入代码。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面有完整的参数说明和示例。最后提醒一个实操细节改完请求头后别只测一次就下结论。连续跑 10 次看成功率。如果偶发失败把失败时的响应体完整打出来看是不是 CF 的 HTML。如果是说明请求头还不够「像浏览器」可以再补Referer、Origin这类头。如果失败时是 JSON 报错那就是业务层问题按第 5 节的分类去查。把「拦截」和「业务报错」分开处理你的排查速度会快很多。