横向对比

Cloudflare 托管挑战与互动挑战

Cloudflare 提供了两种质询操作,站点操作员可以在 WAF 规则中配置:托管质询交互式质询。托管挑战是一种现代的自适应方法 — Cloudflare 决定每个访问者的难度。互动挑战是传统选项,始终呈现可见的验证码。了解差异决定了使用哪种 CaptchaAI 方法以及自动化过程中的期望。


快速比较

特征 管理挑战 互动挑战
介绍 2021年 旧版(2021 年之前)
自适应? 是(Cloudflare 根据访客决定) 否(始终互动)
隐形通行证可能吗? 是(约 90% 的访客以隐形方式通过) 否(始终显示验证码)
使用的挑战类型 隐形→旋转门→ JS挑战 验证码始终可见
Cloudflare 推荐? 是(新规则的默认值) 否(为了向后兼容而保留)
用户摩擦 低(大多数通过但没有看到任何东西) 高(总是需要交互)
HTTP 状态 503 403
CaptchaAI方法 turnstilecloudflare_challenge turnstile

管理挑战(现代)

托管挑战是 Cloudflare 推荐的挑战操作。它使用决策框架来提出尽可能最小的破坏性挑战:

决策流程

WAF rule triggers Managed Challenge
    ↓
Cloudflare evaluates visitor signals:
  ├─ Browser fingerprint quality
  ├─ IP reputation score
  ├─ TLS fingerprint (JA3/JA4)
  ├─ Request history
  ├─ Behavioral signals
  └─ Device capabilities
    ↓
Risk assessment → Challenge level selected:
  ├─ LOW risk → Invisible pass (no visible UI)
  ├─ MEDIUM risk → Non-interactive Turnstile (background PoW)
  ├─ HIGH risk → Interactive Turnstile (checkbox/widget)
  └─ VERY HIGH risk → JavaScript challenge page (5s wait)
    ↓
Challenge completed
    ↓
qa_session_cookie cookie issued

游客体验什么

访客类型 他们看到了什么 百分比
普通浏览器,良好的IP 什么都没有(隐形通行证) 〜90%
新浏览器,中立IP 简短的旋转器 〜5%
可疑信号 Turnstile复选框 〜4%
高风险信号 “正在检查您的浏览器...”页面 〜1%

HTML输出

托管挑战页面使用 Cloudflare 的挑战平台:

<!-- Managed Challenge page (when visible) -->
<body>
    <div id="challenge-stage">
        <div id="challenge-body-text">
            Verifying you are human. This may take a few seconds.
        </div>

        <!-- Turnstile widget (when rendered) -->
        <div class="cf-turnstile"
             data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg">
        </div>
    </div>

    <!-- Challenge platform script -->
    <script src="/cdn-cgi/challenge-platform/h/g/orchestrate/managed/v1?ray=...">
    </script>
</body>

互动挑战(旧版)

互动挑战始终呈现访客必须与之互动的可见验证码。没有隐形的通行证——每个访客都能看到并且必须完成挑战。

它是如何运作的

WAF rule triggers Interactive Challenge
    ↓
Full-page CAPTCHA served (HTTP 403)
    ↓
Visitor must interact with CAPTCHA widget
    ↓
CAPTCHA solved
    ↓
qa_session_cookie cookie issued

游客体验什么

每个访问者都会看到带有类似旋转门的小部件的整页挑战:

<!-- Interactive Challenge page -->
<body>
    <div id="challenge-running">
        <div class="main-wrapper">
            <h2>Please verify you are human</h2>

            <!-- Always-visible challenge widget -->
            <div class="challenge-widget">
                <!-- Checkbox + verification -->
            </div>
        </div>
    </div>
</body>

为什么 Cloudflare 不鼓励这样做

问题 影响
始终可见 100% 的访客看到了挑战
更高的摩擦力 每个访客都必须互动
更高的跳出率 用户离开而不是完成
无风险适应 知名访客也受到挑战
可访问性问题 每个访客都必须完成互动

检测:我面临哪些挑战?

import requests
import re

def identify_challenge_type(url):
    """Determine if a URL uses Managed or Interactive Challenge."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    response = requests.get(url, headers=headers, timeout=15, allow_redirects=False)
    html = response.text
    status = response.status_code

    result = {
        "url": url,
        "status": status,
        "challenge_type": None,
        "cf_ray": response.headers.get("cf-ray", ""),
        "solve_method": None,
    }

    if status == 200:
        # Check for inline Turnstile widget (not a challenge page)
        if "cf-turnstile" in html:
            result["challenge_type"] = "turnstile_widget"
            result["solve_method"] = "turnstile"
        else:
            result["challenge_type"] = "none"
        return result

    if status == 503:
        # 503 indicates Managed Challenge or IUAM
        if "managed" in html or "challenge-platform" in html:
            result["challenge_type"] = "managed_challenge"
            result["solve_method"] = "turnstile"  # Managed renders as Turnstile
        elif "jschl" in html:
            result["challenge_type"] = "iuam_js_challenge"
            result["solve_method"] = "cloudflare_challenge"
        else:
            result["challenge_type"] = "unknown_503"
        return result

    if status == 403:
        if "challenge" in html.lower():
            result["challenge_type"] = "interactive_challenge"
            result["solve_method"] = "turnstile"
        else:
            result["challenge_type"] = "waf_block"
            result["solve_method"] = None  # Hard block, not solvable
        return result

    return result


# Usage
info = identify_challenge_type("https://protected-site.com/login")
print(f"Challenge: {info['challenge_type']}")
print(f"Solve with: {info['solve_method']}")

检测表

信号 管理挑战 互动挑战 国际原子能机构联合会 WAF区块
HTTP状态 503 403 503 403
HTML 中的 challenge-platform
managed 脚本中的路径
HTML 中的 jschl
始终显示小部件
隐形通行证成为可能

解决每种挑战类型

解决管理挑战

托管挑战通常呈现为旋转门小部件。使用CaptchaAI的turnstile方法:

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_managed_challenge(url, sitekey=None):
    """Solve Cloudflare Managed Challenge."""
    # If sitekey not provided, extract from page
    if not sitekey:
        import re
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                          "AppleWebKit/537.36 Chrome/120.0.0.0",
        }
        page = requests.get(url, headers=headers, timeout=15)
        match = re.search(
            r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', page.text
        )
        sitekey = match.group(1) if match else None

    if not sitekey:
        # No visible Turnstile — try cloudflare_challenge method
        return solve_js_challenge(url)

    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "turnstile",
        "sitekey": sitekey,
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Solve timed out")


def solve_js_challenge(url):
    """Fallback to cloudflare_challenge method."""
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "cloudflare_challenge",
        "sitekey": "managed",
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Solve timed out")

解决互动挑战

互动挑战始终显示可见的小部件。使用相同的 turnstile 方法:

def solve_interactive_challenge(url, sitekey):
    """Solve Cloudflare Interactive Challenge (legacy)."""
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "turnstile",
        "sitekey": sitekey,
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Solve timed out")

Node.js(两种类型)

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveCloudflareChallenge(url, type = "managed") {
  const method = type === "js_challenge" ? "cloudflare_challenge" : "turnstile";
  const sitekey =
    type === "js_challenge" ? "managed" : await extractSitekey(url);

  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method,
      sitekey: sitekey || "managed",
      pageurl: url,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Solve timed out");
}

async function extractSitekey(url) {
  try {
    const response = await axios.get(url, {
      headers: { "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0" },
      validateStatus: () => true,
    });
    const match = response.data.match(
      /data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/
    );
    return match ? match[1] : null;
  } catch {
    return null;
  }
}

从交互式迁移到托管

Cloudflare 建议从交互式挑战迁移到托管挑战。如果您要自动化切换的站点:

改变 对自动化的影响
互动 → 托管 可能会开始隐形通过(~90% 的几率)
HTTP 403 → 503 更新状态代码检查
始终可见 → 自适应 小部件可能不是 HTML 格式
相同的站点密钥 CaptchaAI 解决代码保持不变
相同的 qa_session_cookie 输出 Cookie 处理保持不变

快速检测器工作流程

  • 检查页面是否显示间隙质询页面或在应用程序流程中嵌入小部件。
  • 在决定处理路径之前,查找 cf-chl 标记、Turnstile 容器和回调挂钩。
  • 使用页面 URL 和代理身份记录检测结果,以便快速查看重复的目标更改。

故障排除

症状 原因 处理方式
503 没有可见的小部件 管理挑战无形中通过 无需采取任何行动 - 您已通过
503 与“检查您的浏览器” 成功应对 JS 挑战 使用cloudflare_challenge方法
403 带有可见验证码 互动挑战(旧版) 使用turnstile方法
403 没有挑战 WAF 阻塞,不是挑战 更改 IP 或请求模式
挑战类型随机变化 适应信号的管理挑战 应对 Turnstile 和 JS 挑战
一种类型的 qa_session_cookie 被其他类型拒绝 不同的挑战流程,相同的领域 解决出现的任何挑战

常见问题

我应该先尝试管理挑战吗?

是的。现在大多数网站都使用托管挑战。从 turnstile 方法开始,如果页面显示 JavaScript 挑战(带有“检查您的浏览器”的 503),则回退到 cloudflare_challenge

网站可以在不同页面上使用这两种类型吗?

是的,但这种情况并不常见。每个 WAF 规则可以有不同的操作。一项规则可能对 /login 使用托管质询,对 /api/ 使用交互式质询。

是的。两种挑战类型都会生成相同的 qa_session_cookie cookie。无论质询类型如何,cookie 处理都是相同的。

如果“管理挑战”不知不觉地从我身边经过怎么办?

如果托管挑战确定您的请求风险较低,它会在没有明显挑战的情况下通过该请求。您的响应将是带有页面内容的普通 200。在这种情况下不需要 CaptchaAI 求解。

互动挑战是否已被弃用?

Cloudflare 尚未正式弃用它,但他们建议对所有新规则使用托管挑战。互动挑战仍然是为了向后兼容。站点可能随时迁移。


概括

Cloudflare 的托管挑战会自适应地选择每个访问者的挑战难度(对于完整的 JS 挑战来说是不可见的),而交互式挑战始终会呈现可见的验证码。两者都产生相同的 qa_session_cookie cookie 并通过以下方法解决CaptchaAI— 对于大多数挑战使用 turnstile,对于 JavaScript 挑战页面使用 cloudflare_challenge。管理挑战是现代的默认做法;互动挑战是遗产。

相关文章

该文章已禁用评论。