Explainers

Cloudflare 挑战如何运作

打开 Cloudflare 防护的网站,页面卡在“Checking your browser before accessing...”几秒钟——这就是国内开发者常戏称的“五秒盾”。正式名字是 Cloudflare 挑战:判断访问者可能是机器人时弹出的全页拦截,和嵌入页面的小部件 Turnstile 不是一回事。

验证通过后,Cloudflare 下发 qa_session_cookie,后续请求带着它才能继续访问。脚本卡在这一步,多数不是代码写错,而是没处理好绑定规则——下面按流程拆开讲。


哪些信号会触发 Cloudflare 挑战

触发信号 说明
数据中心 IP 请求来自已知的云主机/IDC 网段,而不是家庭宽带出口
请求头缺失或异常 HTTP 头字段缺失,或者和真实浏览器的指纹对不上
TLS 指纹 JA3/JA4 指纹命中了已知的机器人特征库
请求频率过高 短时间内同一 IP 打了太多请求
安全等级调高 站点管理员把挑战阈值设成了 High
地区规则 命中了按国家/地区设置的封锁或挑战规则
机器人分数偏低 Cloudflare 机器学习模型给出的分数不够高
命中威胁情报 该 IP 出现在已知的威胁情报名单里

国内云厂商(阿里云、腾讯云等)机房网段大多能在公开 IDC 库里查到,正好命中第一条“数据中心 IP”;换成家庭宽带出口,触发概率通常明显更低。


挑战是怎么一步步触发并放行的

步骤 说明
1. 请求进站 Cloudflare 反向代理先接管请求,不转发给源站
2. 风险打分 综合 IP 信誉、请求头、TLS 指纹和行为算分
3. 挑战顶替响应 分数不干净时,挑战页直接顶替源站真实响应
4. 浏览器跑 JS 验证 挑战页脚本在浏览器里自动执行检测
5. 写入 qa_session_cookie 通过后签发 cookie,有效期由站点配置
6. 放行重新加载 浏览器带新 cookie 重新请求,拿到真实页面内容
Request → Cloudflare proxy → Suspicious? → Challenge page
                                              ↓
                                    Browser verification
                                              ↓
                                    qa_session_cookie cookie set
                                              ↓
                                    Original page loads

通过挑战后,浏览器会收到:

qa_session_cookie=abc123...; path=/; domain=.example.com; secure; HttpOnly; SameSite=None
属性 说明
有效期 15 分钟到 24 小时,由站点配置,没有统一标准
作用域 只认发放它的域名
绑定关系 和验证时的 User-Agent、IP 强绑定
用法 后续请求都要带着它,否则又被打回挑战页

重要提示: qa_session_cookie 认的是当时那把 User-Agent + IP 组合,换掉任何一个立刻失效——这是脚本最容易踩的坑。


为什么必须配代理

qa_session_cookie 以加密方式绑定三样东西:IP 地址(解出结果必须来自你后续会用的那个 IP)、User-Agent(要和后续请求一致)、TLS 指纹(部分配置还会额外核对)。任意一项对不上,cookie 立刻作废。


Cloudflare 挑战、Turnstile、JS 挑战怎么分辨

特征 Cloudflare 挑战 Turnstile JS 挑战
形式 全页拦截 页面内嵌小部件 静默检测,用户无感
用户能看到什么 “检查你的浏览器”页面 一个复选框,或者什么都不用点 什么都看不到
会不会挡住整页 不会 短暂挡一下
会不会下发 qa_session_cookie 有时候会
解决时要不要代理 不要 不适用
站点必须接入 Cloudflare CDN 吗 必须 可选 必须

用 CaptchaAI 自动解决 Cloudflare 挑战

Python

import requests
import time

API_KEY = "YOUR_API_KEY"

# Submit task — proxy is REQUIRED
response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": API_KEY,
    "method": "cloudflare_challenge",
    "pageurl": "https://example.com/protected-page",
    "proxy": "username:password@proxy.example.com:8080",
    "proxytype": "HTTP",
    "json": 1
})

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

# Poll for result
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:
        solution = result["request"]
        # solution contains qa_session_cookie cookie + user_agent
        print(f"qa_session_cookie: {solution}")
        break

Node.js

const axios = require('axios');

async function solveCloudflareChallenge(pageurl, proxy) {
  const { data } = await axios.get('https://ocr.captchaai.com/in.php', {
    params: {
      key: 'YOUR_API_KEY',
      method: 'cloudflare_challenge',
      pageurl,
      proxy,
      proxytype: 'HTTP',
      json: 1
    }
  });

  const taskId = data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const res = await axios.get('https://ocr.captchaai.com/res.php', {
      params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
    });
    if (res.data.status === 1) return res.data.request;
  }
  throw new Error('Timeout');
}
# After getting the solution
qa_session_cookie = solution["qa_session_cookie"]
user_agent = solution["user_agent"]

# Use the SAME proxy and user agent for subsequent requests
session = requests.Session()
session.cookies.set("qa_session_cookie", qa_session_cookie, domain=".example.com")
session.headers["User-Agent"] = user_agent
session.proxies = {"https": "http://username:password@proxy.example.com:8080"}

# Now access the protected page
page = session.get("https://example.com/protected-page")
print(f"Status: {page.status_code}")

页面同时挂 Cloudflare 挑战和 reCAPTCHA 时,要先过 Cloudflare 拿到 qa_session_cookie,才能加载到显示 reCAPTCHA 的页面,顺序不能颠倒。


常见问题

站点自己配置有效期,一般 15 分钟到 24 小时。过期后旧 cookie 失效,必须重新走一遍流程。

不能。cookie 签发时就和那个 IP 绑死,换 IP 会被要求重新验证;保留会话需代理与签发时一致。

国内机房的 IP 是不是更容易被判定要挑战?

更容易,原因见上文触发信号表:

  • 阿里云、腾讯云等云厂商网段大多被标记“数据中心 IP”
  • 普通家庭宽带出口通常不会被标记

站点把安全等级调高之后,挑战会变得更严格吗?

会。安全等级是管理员自设的阈值,调到 High 后同样行为更容易被判定可疑。脚本突然被频繁拦截,先查目标站点是否刚调整过安全策略。

Cloudflare 挑战本身算不算一种验证码?

不完全算,它看的是 IP、请求头、TLS 指纹这些环境特征,多数时候浏览器后台跑几秒 JS 检测就直接放行;真正弹出图形化交互的通常是 Turnstile 或页面里的 reCAPTCHA。


相关指南

延伸阅读:用 API 自动解决 Cloudflare 挑战Cloudflare 挑战常见错误与修复Cloudflare Turnstile 的工作原理用 API 解决 Cloudflare Turnstile

该文章已禁用评论。