Hướng Dẫn API

Thông số trang thử thách Cloudflare và luồng mã thông báo

Khi Cloudflare hiển thị một trang thử thách, một luồng mã thông báo phức tạp sẽ bắt đầu - từ các tham số trang ban đầu thông qua thực thi JavaScript đến cookie <staging-session-cookie> cuối cùng. Việc hiểu các tham số này giúp bạn chẩn đoán các lỗi giải quyết, gỡ lỗi các luồng tự động hóa và chọn phương pháp giải quyết phù hợp.


Giải phẫu trang thử thách

Trang thử thách Cloudflare (HTTP 503) chứa một số thành phần chính:

<!DOCTYPE html>
<html>
<head>
    <title>Just a moment...</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <div id="challenge-stage">
        <div id="challenge-body-text">
            Checking if the site connection is secure
        </div>
        <div id="challenge-spinner">
            <!-- Loading spinner -->
        </div>
    </div>

    <div id="challenge-form" style="display:none">
        <form id="challenge-form" action="/..." method="POST">
            <!-- Hidden parameters -->
            <input type="hidden" name="md" value="...">
            <input type="hidden" name="r" value="...">
        </form>
    </div>

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

Thông số chính

Trong trang thử thách

tham số Tên Mục đích
ray ID tia Cloudflare Mã định danh yêu cầu duy nhất, liên kết thách thức với yêu cầu ban đầu
md Siêu dữ liệu thử thách Trạng thái thử thách được mã hóa
r Mã thông báo phản hồi Câu trả lời được tính toán (điền bằng JavaScript)
chl_opt Tùy chọn thử thách Cấu hình cho kịch bản thử thách
cRay tia thách thức Tia phụ để theo dõi thử thách
cZone Khu vực thử thách ID vùng đám mây
cUPMDTk Dấu thời gian Thời gian phát hành thử thách
cHash Thử thách băm Xác thực tính toàn vẹn

Trong URL tập lệnh thử thách

/cdn-cgi/challenge-platform/h/g/orchestrate/chl_page/v1?ray=ABC123
thành phần Ý nghĩa
/cdn-cgi/challenge-platform/ Cơ sở hạ tầng thách thức Cloudflare
h/g/ Phiên bản thử thách/variant
orchestrate/ Điểm cuối điều phối thử thách
chl_page/v1 Phiên bản trang thử thách
ray=ABC123 Yêu cầu liên kết Ray ID

Trong tải trọng JavaScript

Tập lệnh thử thách tải các tham số bổ sung:

// Extracted from obfuscated challenge script
window._cf_chl_opt = {
    cvId: '2',           // Challenge version
    cType: 'managed',    // Challenge type
    cNounce: '...',      // Cryptographic nonce
    cRay: '...',         // Challenge Ray ID
    cHash: '...',        // Challenge hash
    cUPMDTk: '...',      // Timestamp
    cFPWv: 'g',          // Fingerprint version
    cTTimeMs: '4000',    // Minimum wait time (ms)
    cTplV: 5,            // Template version
    cLt: '...',          // Challenge lifetime
    cRq: {},             // Challenge request data
};

Luồng mã thông báo từ thử thách đến giải phóng mặt bằng

Luồng từng bước


1. CLIENT → CLOUDFLARE EDGE
   GET /protected-page
   ↓

2. CLOUDFLARE → CLIENT
   HTTP 503 + Challenge page HTML
   Sets: __cf_bm cookie (bot management tracking)
   Contains: ray ID, challenge script URL
   ↓

3. CLIENT (browser)
   Loads challenge script from /cdn-cgi/challenge-platform/...
   ↓

4. CHALLENGE SCRIPT EXECUTES:
   a. Collects browser fingerprint:

      - Canvas hash
      - WebGL renderer
      - Screen dimensions
      - Installed fonts
      - Timezone
      - Language
   b. Runs proof-of-work:

      - Iterates hash computations
      - Must find answer matching difficulty
   c. Computes timing:

      - Enforces minimum wait (cTTimeMs)
      - Records actual timing
   d. Generates response token:

      - Combines fingerprint + PoW answer + timing
      - Encrypts with challenge nonce
   ↓

5. CLIENT → CLOUDFLARE
   POST /cdn-cgi/challenge-platform/h/g/flow/ov1/...
   Body: { r: "encrypted_response", md: "metadata", ... }
   ↓

6. CLOUDFLARE validates:
   - Proof-of-work answer correct?
   - Timing within acceptable range?
   - Fingerprint consistent with real browser?
   - No replay (nonce check)?
   ↓

7. CLOUDFLARE → CLIENT
   HTTP 200 + Set-Cookie: <staging-session-cookie>=...; path=/; expires=...
   + HTTP redirect to original URL
   ↓

8. CLIENT → CLOUDFLARE
   GET /protected-page
   Cookie: <staging-session-cookie>=...
   ↓

9. CLOUDFLARE → CLIENT
   HTTP 200 + Protected content
Request 1: No cookies
    → Challenge page (503)
    → __cf_bm cookie set

Challenge solve:
    → <staging-session-cookie> cookie set

Request 2+: <staging-session-cookie> + __cf_bm
    → Content served (200)

After ~30 mins: <staging-session-cookie> expires
    → Next request triggers new challenge

bánh quy Mục đích Trọn đời Phạm vi
__cf_bm Theo dõi phiên quản lý bot 30 phút Tên miền
<staging-session-cookie> Bằng chứng giải phóng mặt bằng thách thức 15 phút - 24 giờ (có thể định cấu hình) Tên miền
__cflb Mối quan hệ cân bằng tải Phiên Tên miền
_cfuvid ID khách truy cập duy nhất Phiên Tên miền

Cookie <staging-session-cookie> bị ràng buộc với:

  1. Địa chỉ IP — Phải đến từ cùng một IP đã giải quyết thử thách
  2. User-Agent — Phải khớp với UA được sử dụng trong thử thách
  3. Miền — Chỉ hợp lệ cho miền đã phát hành nó
# ❌ FAILS — IP mismatch
# Solve challenge from IP A, then use <staging-session-cookie> from IP B

# ❌ FAILS — UA mismatch
# Solve with Chrome UA, then send requests with Firefox UA

# ✅ WORKS — Same IP + Same UA
session = requests.Session()
session.headers["User-Agent"] = "Mozilla/5.0 ... Chrome/120.0.0.0"
# Use same session for solving and subsequent requests

Trích xuất các tham số thử thách

Python

import re
import requests

def extract_challenge_params(url):
    """Extract Cloudflare challenge page parameters."""
    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

    params = {
        "status_code": response.status_code,
        "cf_ray": response.headers.get("cf-ray", ""),
        "is_challenge": response.status_code == 503,
    }

    if not params["is_challenge"]:
        return params

    # Extract Ray ID from page
    ray_match = re.search(r"ray['\"]?\s*[:=]\s*['\"]([a-f0-9]+)['\"]", html, re.I)
    if ray_match:
        params["ray_id"] = ray_match.group(1)

    # Extract challenge script URL
    script_match = re.search(
        r'src=["\'](/cdn-cgi/challenge-platform/[^"\']+)["\']', html
    )
    if script_match:
        params["challenge_script"] = script_match.group(1)

    # Extract challenge options
    opt_match = re.search(r"_cf_chl_opt\s*=\s*\{([^}]+)\}", html)
    if opt_match:
        opt_text = opt_match.group(1)

        # Parse individual options
        for key in ["cType", "cRay", "cHash", "cTTimeMs", "cvId", "cFPWv"]:
            val_match = re.search(
                rf"{key}\s*:\s*['\"]?([^'\"', }}]+)", opt_text
            )
            if val_match:
                params[key] = val_match.group(1)

    # Extract form parameters
    md_match = re.search(r'name=["\']md["\']\s+value=["\']([^"\']+)["\']', html)
    if md_match:
        params["md"] = md_match.group(1)

    # Extract cookies from response
    params["cookies"] = {
        name: value
        for name, value in response.cookies.items()
    }

    return params

# Usage
params = extract_challenge_params("https://protected-site.com")
if params["is_challenge"]:
    print(f"Challenge type: {params.get('cType', 'unknown')}")
    print(f"Ray ID: {params.get('ray_id', params['cf_ray'])}")
    print(f"Min wait: {params.get('cTTimeMs', '?')}ms")
    print(f"Script: {params.get('challenge_script', 'not found')}")

Node.js

const axios = require("axios");

async function extractChallengeParams(url) {
  const response = await axios.get(url, {
    headers: {
      "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
      Accept: "text/html,*/*;q=0.8",
    },
    validateStatus: () => true,
    maxRedirects: 0,
  });

  const html = response.data;
  const params = {
    statusCode: response.status,
    cfRay: response.headers["cf-ray"] || "",
    isChallenge: response.status === 503,
  };

  if (!params.isChallenge) return params;

  // Extract challenge script URL
  const scriptMatch = html.match(
    /src=["'](\/cdn-cgi\/challenge-platform\/[^"']+)["']/
  );
  if (scriptMatch) params.challengeScript = scriptMatch[1];

  // Extract challenge type
  const typeMatch = html.match(/cType\s*:\s*['"]?(\w+)/);
  if (typeMatch) params.challengeType = typeMatch[1];

  // Extract timing
  const timeMatch = html.match(/cTTimeMs\s*:\s*['"]?(\d+)/);
  if (timeMatch) params.minWaitMs = parseInt(timeMatch[1]);

  return params;
}

extractChallengeParams("https://protected-site.com").then(console.log);

Giải quyết bằng CaptchaAI

CaptchaAI xử lý nội bộ toàn bộ luồng mã thông báo - bạn không cần trích xuất các tham số thử thách theo cách thủ công:

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(target_url):
    """Solve Cloudflare challenge page — CaptchaAI handles token flow."""
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "cloudflare_challenge",
        "sitekey": "managed",
        "pageurl": target_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("Challenge solve timed out")

# CaptchaAI handles the full flow:
# 1. Loads the challenge page
# 2. Executes JavaScript
# 3. Solves proof-of-work
# 4. Returns clearance token/cookies
token = solve_cloudflare_challenge("https://protected-site.com/login")

Gỡ lỗi thử thách thất bại

Điểm thất bại phổ biến

Điểm thất bại Triệu chứng Nguyên nhân gốc rễ
Trang thử thách không tải Hết thời gian chờ hoặc phản hồi trống Sự cố Network/proxy
Tập lệnh không thực thi được Vòng thử thách Thiếu API JavaScript
Bằng chứng công việc không thành công Con quay vô hạn Hết thời gian tính toán
Phản hồi bị từ chối Chuyển hướng trở lại thử thách Vi phạm thời gian hoặc dấu vân tay không khớp
chưa được đặt Thiếu cookie sau khi giải quyết Lỗi phân tích phản hồi
bị từ chối 403 theo yêu cầu tiếp theo IP hoặc UA không khớp

Danh sách kiểm tra gỡ lỗi

def debug_challenge_flow(url, cf_clearance_cookie=None, user_agent=None):
    """Debug the challenge solve flow step by step."""
    ua = user_agent or (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 Chrome/120.0.0.0"
    )

    steps = []

    # Step 1: Initial request
    response = requests.get(
        url,
        headers={"User-Agent": ua, "Accept": "text/html,*/*;q=0.8"},
        timeout=15,
        allow_redirects=False,
    )
    steps.append({
        "step": "initial_request",
        "status": response.status_code,
        "is_challenge": response.status_code == 503,
        "cf_ray": response.headers.get("cf-ray", ""),
    })

    # Step 2: Test with <staging-session-cookie>
    if cf_clearance_cookie:
        session = requests.Session()
        session.cookies.set("<staging-session-cookie>", cf_clearance_cookie)
        session.headers["User-Agent"] = ua

        response2 = session.get(url, timeout=15, allow_redirects=False)
        steps.append({
            "step": "with_clearance",
            "status": response2.status_code,
            "passed": response2.status_code == 200,
        })

        if response2.status_code != 200:
            steps.append({
                "step": "diagnosis",
                "issue": "<staging-session-cookie> rejected",
                "possible_causes": [
                    "Cookie expired",
                    "IP address changed",
                    "User-Agent mismatch",
                    "Cookie from different domain",
                ],
            })

    return steps

Khắc phục sự cố

Triệu chứng nguyên nhân sửa chữa
Loại thử thách được "quản lý" nhưng giải quyết không thành công Thử thách yêu cầu Turnstile chứ không phải thử thách JS Hãy thử phương pháp turnstile thay vì cloudflare_challenge
hoạt động một lần rồi bị từ chối Xoay IP đã thay đổi IP của bạn Ghim IP cho thời gian tồn tại
Trang "Đợi một chút..." không bao giờ giải quyết được JavaScript bị chặn hoặc không đúng định dạng Sử dụng CaptchaAI thay vì giải thủ công
Thử thách xuất hiện lại sau mỗi yêu cầu cf_thông quan không được gửi Đảm bảo cookie được duy trì trong phiên
Thử thách khác nhau trên những con đường khác nhau Quy tắc WAF trên mỗi đường dẫn Giải quyết từng đường dẫn riêng biệt

Câu hỏi thường gặp

Đó là mã thông báo được mã hóa chứa bằng chứng giải quyết, hàm băm IP, hàm băm UA và thời gian hết hạn. Bạn không thể giải mã hoặc giả mạo nó - chỉ cạnh của Cloudflare mới có thể xác thực nó.

kéo dài bao lâu?

Người vận hành trang web định cấu hình thời gian tồn tại. Mặc định là 30 phút. Phạm vi là 15 phút đến 24 giờ. Khách hàng doanh nghiệp có thể đặt giá trị tùy chỉnh.

Tôi có thể giải quyết thử thách mà không cần thực thi JavaScript không?

Không. Thử thách này yêu cầu JavaScript để tính toán bằng chứng công việc và dấu vân tay của trình duyệt. CaptchaAI xử lý việc này nội bộ bằng trình duyệt thực.

Điều gì xảy ra nếu ID Ray thay đổi?

Mỗi yêu cầu nhận được một ID Ray mới. Thử thách được liên kết với ID Ray tại thời điểm trang thử thách. Khi được cấp, ID Ray không còn phù hợp nữa.

Tôi có thể sử dụng lại trên các miền khác nhau không?

Không. có phạm vi tên miền. Mỗi miền yêu cầu cookie giải quyết và giải quyết thách thức riêng.


Tóm tắt

Các trang thử thách của Cloudflare chứa ID Ray, tập lệnh thử thách, đối tượng tùy chọn và tham số biểu mẫu điều khiển luồng mã thông báo bằng chứng công việc. Luồng tạo ra cookie <staging-session-cookie> được liên kết với IP và Tác nhân người dùng, có hiệu lực trong 15 phút đến 24 giờ. VớiCaptchaAI, bạn không cần phải phân tích cú pháp các tham số này theo cách thủ công — bộ giải sẽ xử lý toàn bộ luồng. Để gỡ lỗi, việc hiểu các tham số sẽ giúp xác định vị trí ngắt luồng.

bài viết liên quan

  • Cloudflare Challenge Vs Phát hiện cửa quay
  • Thử thách tương tác và quản lý Cloudflare
  • Cloudflare Turnstile 403 Sau khi sửa mã thông báo
Os comentários estão desativados para este artigo.