大多数 Cloudflare Turnstile 失败都不是随机的。它们分为三类:请求阶段错误(您向 API 的提交被拒绝)、结果阶段错误(轮询失败或超时)和目标页面验证失败(API 返回有效令牌,但页面仍然拒绝它)。
旋转栅门的三个最大的特定问题是:
- 确切的页面 URL 错误 — 尤其是在 Cloudflare 挑战页面上,上下文更加严格
- 错误的站点密钥 — 从错误的元素或不同的小部件实例捕获
- 通过错误路径应用令牌 — 页面需要
cf-turnstile-response、回调或两者兼而有之
CaptchaAI 解决旋转栅门问题100% 成功率不到 10 秒。当您的集成失败时,问题几乎总是在于您发送的参数或如何应用返回的令牌。
旋转栅门特定的故障点
在深入研究错误代码之前,请了解 Turnstile 与其他验证码类型不同的三点:
1. 准确的页面 URL 更重要
Turnstile 令牌与页面上下文紧密绑定。在 Cloudflare 质询页面(全页验证屏幕)上,使用错误的 URL(即使路径略有不同)将导致令牌被拒绝。
2. 两种代币申请路径
返回的令牌可以通过两种方式应用,使用错误的一种方式将会失败:
| 方法 | 何时使用 |
|---|---|
隐藏字段 — 插入到 cf-turnstile-response(有时是 g-recaptcha-response) |
当页面使用带有隐藏输入的标准表单时 |
回调函数 — 调用 turnstile.render() 或 data-callback 中定义的函数 |
当页面使用编程验证而不是表单时 |
3. 代币是一次性的
Turnstile 令牌只能验证一次。如果您的自动化意外地提交了两次,或者存在竞争条件,则第二次尝试将失败。
请求阶段错误
这些情况发生在向 https://ocr.captchaai.com/in.php 提交任务时。
ERROR_WRONG_USER_KEY
原因: API密钥格式不正确(应为32个字符)。
修复:验证密钥captchaai.com/api.php。
ERROR_KEY_DOES_NOT_EXIST
原因: 密钥格式正确,但未链接到活动帐户。
修复: 检查您的仪表板。确保帐户处于活动状态并且密钥正确。
ERROR_ZERO_BALANCE
原因: 您的计划中没有免费线程。
修复: 等待线程释放、降低并发性或升级。
ERROR_PAGEURL
原因: pageurl 参数丢失。
修复: 添加完整的 URL — 协议、域和路径:
pageurl=https://staging.example.com/qa-login
ERROR_BAD_PARAMETERS
原因: 必需的参数丢失或格式错误。对于旋转门,所需的参数是:
| 范围 | 类型 | 必需的 | 描述 |
|---|---|---|---|
key |
细绳 | 是的 | 您的 CaptchaAI API 密钥 |
method |
细绳 | 是的 | 必须是 turnstile |
sitekey |
细绳 | 是的 | 旋转栅门小部件 sitekey |
pageurl |
细绳 | 是的 | 完整页面网址 |
可选但有用:
| 范围 | 类型 | 描述 |
|---|---|---|
action |
细绳 | data-action 或 turnstile.render() 中的 action 参数的值 |
proxy |
细绳 | 格式:login:password@IP:PORT |
proxytype |
细绳 | HTTP、HTTPS、SOCKS4、SOCKS5 |
修复: 验证所有必填字段是否存在且输入正确。
HTML 或 500/502 响应
原因: 暂时的服务器端错误。
修复: 等待 5-10 秒,然后重试。
如何找到 Turnstile 站点密钥
sitekey 是最常见的错误参数。在这里可以找到它:
选项 1 — data-sitekey 属性:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAB1example"></div>
选项 2 — turnstile.render() 调用:
turnstile.render('#captcha-container', {
sitekey: '0x4AAAAAAAB1example',
callback: function(token) {
document.getElementById('cf-turnstile-response').value = token;
}
});
选项 3 — 拦截渲染调用(高级):
如果sitekey是动态加载的,您可以在小部件初始化之前重新定义turnstile.render以捕获参数:
// Inject this before the Turnstile script loads
const originalRender = window.turnstile.render;
window.turnstile.render = function(container, params) {
console.log('Sitekey:', params.sitekey);
console.log('Action:', params.action);
return originalRender.call(this, container, params);
};
结果阶段错误
这些发生在轮询 https://ocr.captchaai.com/res.php 时。
CAPCHA_NOT_READY
不是错误。 解决仍在进行中。旋转门在 CaptchaAI 处求解通常需要不到 10 秒。
修复: 等待 5 秒并再次轮询。
ERROR_WRONG_ID_FORMAT
原因: 验证码 ID 包含非数字字符。
修复: 使用 in.php 返回的确切 ID,未经修改。
ERROR_WRONG_CAPTCHA_ID
原因: ID与任何提交的任务都不匹配。
修复: 验证您正在从提交响应中轮询正确的 ID。
ERROR_EMPTY_ACTION
原因: 您的轮询请求中缺少 action 参数。
修复: 始终包含 action=get:
https://ocr.captchaai.com/res.php?key=YOUR_KEY&action=get&id=CAPTCHA_ID&json=1
注意: 对于 Turnstile,请始终在投票请求中使用
json=1。 JSON 响应可能包括求解器的user_agent,某些受 Cloudflare 保护的页面需要该值才能成功进行令牌验证。
ERROR_CAPTCHA_UNSOLVABLE
原因: 解决失败 - 可能是错误的站点密钥或不受支持的页面配置。
修复: 验证站点密钥,刷新请求,然后重试。
ERROR_INTERNAL_SERVER_ERROR
原因: 服务器端问题。
修复: 等待 10 秒然后重试。
目标页面验证失败
这些是最难调试的,因为 API 成功返回令牌,但目标页面拒绝它。
失败1:令牌插入错误的字段
症状: 表单已提交,但页面返回验证错误或刷新。
Turnstile 页面可以期待不同字段中的令牌:
cf-turnstile-response— 主要 Turnstile 隐藏输入g-recaptcha-response— 某些页面使用此作为后备
修复: 检查页面表单的两个字段。在浏览器自动化中:
# Selenium — inject into both fields for safety
driver.execute_script("""
var cfField = document.querySelector('[name="cf-turnstile-response"]');
var gField = document.querySelector('[name="g-recaptcha-response"]');
if (cfField) cfField.value = arguments[0];
if (gField) gField.value = arguments[0];
""", token)
失败2:回调未触发
症状: 令牌在字段中,但表单仍然阻止提交。
原因: 页面使用回调函数代替(或附加)隐藏字段。回调处理其他逻辑,例如启用提交按钮或发送 AJAX 请求。
修复: 查找并调用回调:
// Check data-callback attribute
const callbackName = document.querySelector('.cf-turnstile').getAttribute('data-callback');
if (callbackName && window[callbackName]) {
window[callbackName](token);
}
// Or if it was passed in turnstile.render()
// You may need to intercept the render call to capture it
失败3:错误的确切页面上下文
症状: 尽管站点密钥正确且解决方案正确,但令牌仍被拒绝。
原因: API请求中使用的pageurl与页面的实际上下文不匹配。这在以下方面尤其常见:
- Cloudflare 挑战页面 — URL 可能包含重要的查询参数或路径组件
- 单页应用程序 — 可见的 URL 可能与加载 Turnstile 小部件的 URL 不同
修复: 使用 DevTools Network 选项卡查找 Turnstile 小部件加载的确切 URL。使用该 URL 作为 pageurl。
失败四:Token重用
症状: 第一个解决有效,后续解决失败。
原因: Turnstile令牌是一次性的。一旦通过 Cloudflare 的服务器验证,令牌就会失效。
修复:为每个表单提交请求一个新的解决方案。不要缓存或重复使用令牌。
快速错误修复参考
| 错误/症状 | 阶段 | 可能的原因 | 处理方式 |
|---|---|---|---|
ERROR_WRONG_USER_KEY |
提交 | API 密钥格式错误 | 验证 32 个字符的密钥 |
ERROR_KEY_DOES_NOT_EXIST |
提交 | 密钥无效 | 检查仪表板 |
ERROR_ZERO_BALANCE |
提交 | 没有空闲线程 | 等待或升级计划 |
ERROR_PAGEURL |
提交 | 缺少 pageurl |
添加完整网址 |
ERROR_BAD_PARAMETERS |
提交 | 缺少 sitekey、方法或 pageurl | 验证所有必填字段 |
CAPCHA_NOT_READY |
轮询 | 解决中 | 等待 5 秒,重试 |
ERROR_WRONG_ID_FORMAT |
轮询 | 非数字验证码 ID | 使用 in.php 中的准确 ID |
ERROR_WRONG_CAPTCHA_ID |
轮询 | 验证码 ID 无效 | 验证提交 ID |
ERROR_EMPTY_ACTION |
轮询 | 缺少 action=get |
添加动作参数 |
| 令牌被页面拒绝 | 验证 | 字段错误、回调未触发、URL错误 | 检查字段名称,调用回调,验证确切的pageurl |
| 第二次解决失败 | 验证 | 代币重用 | 每次提交请求新的令牌 |
Python:完整的旋转门解决方案
import time
import requests
API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SITEKEY = "0x4AAAAAAAB1example"
PAGE_URL = "https://staging.example.com/qa-login"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def solve_turnstile(api_key, sitekey, pageurl):
"""Submit a Turnstile challenge and return the solved token."""
# Submit
submit_resp = requests.post(
SUBMIT_URL,
data={
"key": api_key,
"method": "turnstile",
"sitekey": sitekey,
"pageurl": pageurl,
"json": 1,
},
timeout=30,
)
submit_resp.raise_for_status()
submit_data = submit_resp.json()
if submit_data.get("status") != 1:
raise RuntimeError(f"Submit failed: {submit_data}")
captcha_id = submit_data["request"]
print(f"Task created — captcha ID: {captcha_id}")
# Wait before first poll (Turnstile is fast — 10 seconds is usually enough)
time.sleep(10)
# Poll for result
for _ in range(60):
result_resp = requests.get(
RESULT_URL,
params={
"key": api_key,
"action": "get",
"id": captcha_id,
"json": 1,
},
timeout=30,
)
result_resp.raise_for_status()
result_data = result_resp.json()
if result_data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result_data.get("status") == 1:
return result_data["request"]
raise RuntimeError(f"Polling error: {result_data}")
raise TimeoutError("Turnstile solve timed out")
# Usage
token = solve_turnstile(API_KEY, SITEKEY, PAGE_URL)
print(f"Solved token: {token[:80]}...")
# Inject into cf-turnstile-response and/or g-recaptcha-response
# Then submit the form
Node.js:完整的 Turnstile 解决方案
const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SITEKEY = "0x4AAAAAAAB1example";
const PAGE_URL = "https://staging.example.com/qa-login";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function solveTurnstile(apiKey, sitekey, pageurl) {
// Submit
const submitResp = await fetch(SUBMIT_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
key: apiKey,
method: "turnstile",
sitekey: sitekey,
pageurl: pageurl,
json: "1",
}),
});
const submitData = await submitResp.json();
if (submitData.status !== 1) {
throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
}
const captchaId = submitData.request;
console.log(`Task created — captcha ID: ${captchaId}`);
// Turnstile is fast — wait 10 seconds before first poll
await sleep(10_000);
// Poll for result
for (let i = 0; i < 60; i++) {
const resultResp = await fetch(
`${RESULT_URL}?${new URLSearchParams({
key: apiKey,
action: "get",
id: captchaId,
json: "1",
})}`
);
const resultData = await resultResp.json();
if (resultData.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (resultData.status === 1) {
return resultData.request;
}
throw new Error(`Polling error: ${JSON.stringify(resultData)}`);
}
throw new Error("Turnstile solve timed out");
}
// Usage
solveTurnstile(API_KEY, SITEKEY, PAGE_URL)
.then((token) => {
console.log(`Solved token: ${token.slice(0, 80)}...`);
// Inject into cf-turnstile-response and/or g-recaptcha-response
})
.catch(console.error);
Turnstile 与 Cloudflare 验证流程:您面对的是哪一个?
| 信号 | 旋转门 | Cloudflare 验证流程 |
|---|---|---|
| 你所看到的 | 页面上嵌入的小部件(复选框或不可见) | 全页 Cloudflare 验证屏幕 |
| CaptchaAI 返回什么 | 要注入表单的令牌 | 一个 qa_session_cookie cookie |
| API方法 | turnstile |
cloudflare_challenge |
| 需要代理吗? | 选修的 | 是(必填) |
如果您要参加全页 Cloudflare 挑战(不是嵌入式小部件),您需要Cloudflare 验证流程 求解器相反,它返回 qa_session_cookie cookie 并需要代理。
常问问题
即使请求看起来正确,为什么 Turnstile 也会失败?
三个最常见的原因:(1) pageurl 略有错误 - 尤其是在 Cloudflare 挑战页面上,(2) 从错误的元素捕获了 sitekey,或者 (3) 令牌被注入到错误的字段或回调路径中。
旋转栅门最常见的错误是什么?
使用错误的确切页面 URL。 Turnstile 令牌与页面上下文紧密绑定 - 即使不同的路径或缺少查询参数也可能导致拒绝。
CAPCHA_NOT_READY 是什么意思?
解决仍在进行中。等待 5 秒并再次轮询。 Turnstile 求解通常在 10 秒内完成。
如果API返回token但页面仍然拒绝怎么办?
- 验证
pageurl与小部件加载的确切页面匹配。 - 检查页面是否需要
cf-turnstile-response、g-recaptcha-response或两者中的令牌。 - 检查页面是否使用回调函数来代替(或附加)隐藏字段。
- 确保令牌仅使用一次 - Turnstile 令牌是一次性的。
CaptchaAI 支持 Turnstile 代理吗?
是的。将 proxy 和 proxytype 添加到您的请求中。对于独立的 Turnstile 小部件,代理是可选的,但在 Cloudflare 挑战页面上建议使用代理。
旋转栅门和 Cloudflare 验证流程 有什么区别?
Turnstile 是一个返回令牌的嵌入式小部件。 Cloudflare 验证流程 是返回 qa_session_cookie cookie 的全页验证。尽管都是 Cloudflare 产品,但它们使用不同的 API 方法和不同的集成模式。
修复您的Turnstile工作流程
如果您的 Turnstile 集成失败:
- 验证站点密钥 — 从
data-sitekey或turnstile.render()中提取 - 验证 pageurl — 使用准确的 URL,包括协议和路径
- 检查令牌路径 — 页面是否使用
cf-turnstile-response、g-recaptcha-response或回调? - 使用
json=1— 轮询 Turnstile 结果时始终使用 JSON 响应 - 不要重复使用令牌 - 为每次提交请求一个新的解决方案
从CaptchaAI 旋转门求解器,根据以下内容验证您的参数API文档,并阅读Cloudflare Turnstile 的工作原理如果您需要小部件机制的背景知识。
迭代日志
| 迭代 | 重点 | 变化 |
|---|---|---|
| 草案1 | 结构和内容 | 初始故障排除草案 — 3 个错误阶段、错误修复表、常见问题解答 |
| 草案2 | 技术准确性 | 针对 captchaai.com/api-docs. 验证了错误代码、Turnstile 参数和令牌路径 添加了参数表。已确认 method=turnstile 和 cf-turnstile-response / g-recaptcha-response 字段。 |
| 草案3 | 代码和注入深度 | 添加了 Python 和 Node.js 解决示例。添加了站点密钥提取方法(3 种方法)。为两个令牌字段添加了 Selenium 注入代码。添加了回调检测代码。 |
| 草案4 | 差异化内容 | 添加了 Turnstile 与 Cloudflare 验证流程 比较表。添加了 user_agent 的 json=1 要求说明。添加了动态站点键的渲染拦截技术。 |
| 草案5 | 最终 QA 润色 | 已验证所有错误代码与官方文档相符。添加了快速参考表。收紧简介。添加了一次性令牌警告。已确认集群文章的交叉链接。常见问题解答已准备好架构。 |
视觉资产简介
英雄形象
- 替代文本: 开发人员对 Cloudflare Turnstile 错误进行故障排除 - 请求流、token 提交和验证失败
- 必须显示: 包含错误阶段和修复路径的技术故障排除流程
- 文件名: cloudflare-turnstile-errors-troubleshooting-hero.png
文章内视觉1
- 放置: 在“结果阶段错误”之后
- 类型: 决策树
- 替代文本: Cloudflare Turnstile 失败的决策树 - 请求错误与轮询错误与页面拒绝
- 文件名: cloudflare-turnstile-error-decision-tree.png
文章内视觉2
- 放置: 在“目标页面验证失败”之后
- 类型: 原因与修复图
- 替代文本: 图表显示旋转栅门令牌被拒绝的原因以及每个原因的修复方法
- 文件名: cloudflare-turnstile-validation-causes-fixes.png