故障排查

Cloudflare Turnstile 错误和故障排除

大多数 Cloudflare Turnstile 失败都不是随机的。它们分为三类:请求阶段错误(您向 API 的提交被拒绝)、结果阶段错误(轮询失败或超时)和目标页面验证失败(API 返回有效令牌,但页面仍然拒绝它)。

旋转栅门的三个最大的特定问题是:

  1. 确切的页面 URL 错误 — 尤其是在 Cloudflare 挑战页面上,上下文更加严格
  2. 错误的站点密钥 — 从错误的元素或不同的小部件实例捕获
  3. 通过错误路径应用令牌 — 页面需要 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-actionturnstile.render() 中的 action 参数的值
proxy 细绳 格式:login:password@IP:PORT
proxytype 细绳 HTTPHTTPSSOCKS4SOCKS5

修复: 验证所有必填字段是否存在且输入正确。

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但页面仍然拒绝怎么办?

  1. 验证 pageurl 与小部件加载的确切页面匹配。
  2. 检查页面是否需要 cf-turnstile-responseg-recaptcha-response 或两者中的令牌。
  3. 检查页面是否使用回调函数来代替(或附加)隐藏字段。
  4. 确保令牌仅使用一次 - Turnstile 令牌是一次性的。

CaptchaAI 支持 Turnstile 代理吗?

是的。将 proxyproxytype 添加到您的请求中。对于独立的 Turnstile 小部件,代理是可选的,但在 Cloudflare 挑战页面上建议使用代理。

旋转栅门和 Cloudflare 验证流程 有什么区别?

Turnstile 是一个返回令牌的嵌入式小部件。 Cloudflare 验证流程 是返回 qa_session_cookie cookie 的全页验证。尽管都是 Cloudflare 产品,但它们使用不同的 API 方法和不同的集成模式。


修复您的Turnstile工作流程

如果您的 Turnstile 集成失败:

  1. 验证站点密钥 — 从 data-sitekeyturnstile.render() 中提取
  2. 验证 pageurl — 使用准确的 URL,包括协议和路径
  3. 检查令牌路径 — 页面是否使用 cf-turnstile-responseg-recaptcha-response 或回调?
  4. 使用 json=1 — 轮询 Turnstile 结果时始终使用 JSON 响应
  5. 不要重复使用令牌 - 为每次提交请求一个新的解决方案

CaptchaAI 旋转门求解器,根据以下内容验证您的参数API文档,并阅读Cloudflare Turnstile 的工作原理如果您需要小部件机制的背景知识。


迭代日志

迭代 重点 变化
草案1 结构和内容 初始故障排除草案 — 3 个错误阶段、错误修复表、常见问题解答
草案2 技术准确性 针对 captchaai.com/api-docs. 验证了错误代码、Turnstile 参数和令牌路径 添加了参数表。已确认 method=turnstilecf-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

相关文章

该文章已禁用评论。