API-Tutorials

Cloudflare Challenge-Seitenparameter und Token-Fluss

Wenn Cloudflare eine Challenge-Seite präsentiert, beginnt ein komplexer Token-Fluss – von den ersten Seitenparametern über die JavaScript-Ausführung bis zum endgültigen cf_clearance-Cookie. Das Verständnis dieser Parameter hilft Ihnen, Lösungsfehler zu diagnostizieren, Automatisierungsflüsse zu debuggen und den richtigen Lösungsansatz auszuwählen.


Anatomie der Herausforderungsseite

Eine Cloudflare-Challenge-Seite (HTTP 503) enthält mehrere Schlüsselelemente:

<!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>

Schlüsselparameter

Auf der Challenge-Seite

Parameter Name Zweck
ray Cloudflare Ray-ID Eindeutiger Anforderungsbezeichner, der die Herausforderung mit der ursprünglichen Anforderung verknüpft
md Fordern Sie Metadaten heraus Verschlüsselter Challenge-Status
r Antworttoken Berechnete Antwort (ausgefüllt mit JavaScript)
chl_opt Herausforderungsoptionen Konfiguration für das Challenge-Skript
cRay Herausforderungsstrahl Sekundärstrahl zur Herausforderungsverfolgung
cZone Herausforderungszone Cloudflare-Zonen-ID
cUPMDTk Zeitstempel Zeitpunkt der Herausforderungsausgabe
cHash Challenge-Hash Integritätsvalidierung

In der Challenge-Skript-URL

/cdn-cgi/challenge-platform/h/g/orchestrate/chl_page/v1?ray=ABC123
Komponente Bedeutung
/cdn-cgi/challenge-platform/ Cloudflare-Challenge-Infrastruktur
h/g/ Herausforderungsversion/variant
orchestrate/ Challenge-Orchestrierungsendpunkt
chl_page/v1 Version der Herausforderungsseite
ray=ABC123 Fordern Sie eine Ray-ID-Bindung an

In der JavaScript-Nutzlast

Das Challenge-Skript lädt zusätzliche Parameter:

// 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
};

Token-Fluss von der Herausforderung bis zur Freigabe

Schritt-für-Schritt-Ablauf


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: cf_clearance=...; path=/; expires=...
   + HTTP redirect to original URL
   ↓

8. CLIENT → CLOUDFLARE
   GET /protected-page
   Cookie: cf_clearance=...
   ↓

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

Challenge solve:
    → cf_clearance cookie set

Request 2+: cf_clearance + __cf_bm
    → Content served (200)

After ~30 mins: cf_clearance expires
    → Next request triggers new challenge

Challenge-Cookies

Keks Zweck Lebenszeit Umfang
__cf_bm Nachverfolgung von Bot-Management-Sitzungen 30 Min Domäne
cf_clearance Fordern Sie den Freigabenachweis an 15 Min. – 24 Std. (konfigurierbar) Domäne
__cflb Load-Balancer-Affinität Sitzung Domäne
_cfuvid Eindeutige Besucher-ID Sitzung Domäne

Das cf_clearance-Cookie ist gebunden an:

  1. IP-Adresse – Muss von derselben IP stammen, die die Herausforderung gelöst hat
  2. User-Agent – Muss mit der während der Herausforderung verwendeten UA übereinstimmen
  3. Domain – Gilt nur für die Domain, die es ausgestellt hat
# ❌ FAILS — IP mismatch
# Solve challenge from IP A, then use cf_clearance 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

Herausforderungsparameter extrahieren

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);

Lösung mit CaptchaAI

CaptchaAI verwaltet den gesamten Token-Fluss intern – Sie müssen die Challenge-Parameter nicht manuell extrahieren:

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")

Debuggen von Herausforderungsfehlern

Häufige Fehlerquellen

Fehlerstelle Symptom Grundursache
Die Challenge-Seite wird nicht geladen Timeout oder leere Antwort Problem mit Network/proxy
Das Skript kann nicht ausgeführt werden Herausforderungsschleifen Fehlende JavaScript-APIs
Der Arbeitsnachweis schlägt fehl Unendlicher Spinner Rechenzeitüberschreitung
Antwort abgelehnt Zurück zur Herausforderung weiterleiten Timing-Verletzung oder Browser-Signalprofil-Nichtübereinstimmung
cf_clearance nicht gesetzt Cookie fehlt nach Lösung Fehler beim Parsen der Antwort
cf_clearance abgelehnt 403 auf spätere Anfrage IP- oder UA-Nichtübereinstimmung

Debugging-Checkliste

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 cf_clearance
    if cf_clearance_cookie:
        session = requests.Session()
        session.cookies.set("cf_clearance", 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": "cf_clearance rejected",
                "possible_causes": [
                    "Cookie expired",
                    "IP address changed",
                    "User-Agent mismatch",
                    "Cookie from different domain",
                ],
            })

    return steps

Fehlerbehebung

Symptom Ursache Beheben
Der Herausforderungstyp ist „verwaltet“, aber die Lösung schlägt fehl Die Herausforderung erfordert ein Drehkreuz, keine JS-Herausforderung Versuchen Sie die Methode turnstile anstelle von cloudflare_challenge
cf_clearance funktioniert einmal und wird dann abgelehnt Durch die IP-Rotation wurde Ihre IP geändert Pin-IP für die Lebensdauer des Abstands
Die Seite „Einen Moment…“ wird nie aufgelöst JavaScript blockiert oder fehlerhaft Verwenden Sie CaptchaAI anstelle der manuellen Lösung
Die Herausforderung erscheint nach jeder Anfrage erneut cf_clearance wird nicht gesendet Stellen Sie sicher, dass Cookies während der Sitzung bestehen bleiben
Unterschiedliche Herausforderung auf unterschiedlichen Wegen WAF-Regeln pro Pfad Lösen Sie für jeden Pfad separat auf

Häufig gestellte Fragen

Es handelt sich um ein verschlüsseltes Token, das den Lösungsnachweis, den IP-Hash, den UA-Hash und die Ablaufzeit enthält. Sie können es nicht entschlüsseln oder fälschen – nur der Edge von Cloudflare kann es validieren.

Wie lange dauert cf_clearance?

Site-Betreiber konfigurieren die Lebensdauer. Der Standardwert beträgt 30 Minuten. Der Bereich liegt zwischen 15 Minuten und 24 Stunden. Unternehmenskunden können benutzerdefinierte Werte festlegen.

Kann ich die Herausforderung ohne JavaScript-Ausführung lösen?

Nein. Für die Herausforderung ist JavaScript erforderlich, um den Proof-of-Work und den Browser-Signalprofil zu berechnen. CaptchaAI erledigt dies intern mit echten Browsern.

Was passiert, wenn sich die Ray-ID ändert?

Jede Anfrage erhält eine neue Ray-ID. Die Challenge ist an die Ray-ID zum Zeitpunkt der Challenge-Seite gebunden. Sobald cf_clearance ausgegeben wird, ist die Ray-ID nicht mehr relevant.

Kann ich cf_clearance in verschiedenen Domänen wiederverwenden?

Nein. cf_clearance ist domänenbezogen. Für jede Domain ist ein eigenes Challenge-Löse- und Clearance-Cookie erforderlich.


Zusammenfassung

Cloudflare-Challenge-Seiten enthalten Ray-IDs, Challenge-Skripte, Optionsobjekte und Formularparameter, die einen Proof-of-Work-Token-Flow steuern. Der Flow erzeugt ein cf_clearance-Cookie, das an IP und User-Agent gebunden ist und 15 Minuten bis 24 Stunden gültig ist. Mit CaptchaAI, müssen Sie diese Parameter nicht manuell analysieren – der Solver verarbeitet den gesamten Fluss. Beim Debuggen hilft das Verständnis der Parameter dabei, zu erkennen, wo der Fluss unterbrochen wird.

Verwandte Artikel

Kommentare sind für diesen Artikel deaktiviert.