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
Cookie-Zeitleiste
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 |
cf_clearance-Cookie-Einschränkungen
Das cf_clearance-Cookie ist gebunden an:
- IP-Adresse – Muss von derselben IP stammen, die die Herausforderung gelöst hat
- User-Agent – Muss mit der während der Herausforderung verwendeten UA übereinstimmen
- 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
Was ist im cf_clearance-Cookie enthalten?
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
- Cloudflare Challenge: Wie es funktioniert
- Cloudflare Managed vs. Interactive Challenge
- Cloudflare Turnstile Fehler beheben