Bir isteğiniz HTTP 503 ve Just a moment... sayfasıyla karşılanıyorsa, Cloudflare arka planda çok adımlı bir doğrulama akışı çalıştırıyordur: parametreleri toplar, JavaScript yürütür ve sonunda qa_session_cookie üretir. Parametreleri tanımak, iş akışınızın hangi adımda takıldığını görmenizi sağlar.
Senaryo tanıdık gelecek: İstanbul'daki bir ekip ödeme akışını test ediyor, doğrulama sayfası geliyor ama çerez ayarlanmıyor. Aşağıda önce parametreleri, sonra token akışını, en sonda da akışı CaptchaAI ile tek çağrıya indirmeyi göreceksiniz.
Bu rehberde ele alınanlar:
- 503 sayfasındaki
ray,md,rve_cf_chl_optalanları - Token akışının dokuz adımı
qa_session_cookieçerezinin IP ve UA bağı- Parametreleri kodla çıkarma ve akışı CaptchaAI'ye devretme
503 doğrulama sayfasında ne bulunur
Cloudflare doğrulama sunduğunda dönen HTML iskeleti sadedir: bir durum alanı, gizli bir form ve /cdn-cgi/challenge-platform/ altından yüklenen bir betik. Asıl iş betiğin içinde yürür.
<!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>
Sayfadaki anahtar parametreler
Akışı yöneten değerler üç yerde bulunur: HTML gövdesi, betik URL'si ve JavaScript yükü. Önce gövdedeki alanlar:
| Parametre | Açıklama | İşlevi |
|---|---|---|
ray |
Cloudflare Ray ID | Benzersiz istek tanımlayıcısı; doğrulamayı özgün isteğe bağlar |
md |
Doğrulama meta verisi | Şifrelenmiş doğrulama durumu |
r |
Yanıt token'ı | JavaScript'in hesaplayıp doldurduğu yanıt |
chl_opt |
Doğrulama seçenekleri | Doğrulama betiğinin yapılandırması |
cRay |
İkincil Ray | Doğrulama takibi için ek ray değeri |
cZone |
Doğrulama bölgesi | Cloudflare bölge (zone) kimliği |
cUPMDTk |
Zaman damgası | Doğrulamanın verildiği an |
cHash |
Bütünlük hash'i | Değişmezlik doğrulaması |
Doğrulama betiği URL'sindeki bileşenler
/cdn-cgi/challenge-platform/h/g/orchestrate/chl_page/v1?ray=ABC123
| Bileşen | Anlamı |
|---|---|
/cdn-cgi/challenge-platform/ |
Cloudflare doğrulama altyapısı |
h/g/ |
Doğrulama sürümü/varyantı |
orchestrate/ |
Orkestrasyon uç noktası |
chl_page/v1 |
Doğrulama sayfası sürümü |
ray=ABC123 |
İsteğe bağlı Ray ID |
JavaScript yükündeki parametreler
Betik çalışınca window._cf_chl_opt ek alanlar yükler: doğrulama tipi, zamanlama, şablon sürümü.
// 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', // test profil yapılandırması version
cTTimeMs: '4000', // Minimum wait time (ms)
cTplV: 5, // Template version
cLt: '...', // Challenge lifetime
cRq: {}, // Challenge request data
};
Token akışı: doğrulamadan izne dokuz adım
Akış istemci ile Cloudflare arasında dokuz adımda ilerler: betik tarayıcı sinyallerini toplar, proof-of-work hesaplar ve şifreli bir yanıt token'ı üretir; Cloudflare doğrularsa qa_session_cookie verir:
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 test profil yapılandırması:
- canvas QA tanılama
- 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 test profil yapılandırması + 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?
- test profil yapılandırması consistent with real browser?
- No replay (nonce check)?
↓
7. CLOUDFLARE → CLIENT
HTTP 200 + Set-Cookie: qa_session_cookie=...; path=/; expires=...
+ HTTP redirect to original URL
↓
8. CLIENT → CLOUDFLARE
GET /protected-page
Cookie: qa_session_cookie=...
↓
9. CLOUDFLARE → CLIENT
HTTP 200 + Protected content
Çerez zaman çizelgesi
İlk istekte çerez yoktur; doğrulama çözülünce qa_session_cookie ayarlanır ve süresi dolana kadar sonraki istekleri geçirir:
Request 1: No cookies
→ Challenge page (503)
→ __cf_bm cookie set
Challenge solve:
→ qa_session_cookie cookie set
Request 2+: qa_session_cookie + __cf_bm
→ Content served (200)
After ~30 mins: qa_session_cookie expires
→ Next request triggers new challenge
Doğrulama çerezleri ve qa_session_cookie kısıtları
Akıştaki çerezler arasında asıl belirleyici qa_session_cookie'dir:
| Çerez | İşlevi | Ömrü | Kapsam |
|---|---|---|---|
__cf_bm |
Bot yönetimi oturum takibi | 30 dakika | Alan adı |
qa_session_cookie |
Doğrulama izni kanıtı | 15 dakika – 24 saat (yapılandırılabilir) | Alan adı |
__cflb |
Yük dengeleyici benzeşimi | Oturum | Alan adı |
_cfuvid |
Benzersiz ziyaretçi kimliği | Oturum | Alan adı |
qa_session_cookie taşınabilir bir çerez değildir; üç koşula bağlıdır:
- IP adresi — doğrulamayı çözen IP ile aynı olmalıdır
- User-Agent — doğrulama sırasında kullanılan UA ile eşleşmelidir
- Alan adı — yalnızca çerezi veren alan için geçerlidir
# ❌ FAILS — IP mismatch
# Solve challenge from IP A, then use qa_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
Parametreleri kodla çıkarma
Akışın nerede koptuğunu görmek için önce parametreleri okumanız gerekir. İki örnek 503 yanıtını yakalar ve ray, betik URL'si, doğrulama tipi ile bekleme süresini ayıklar.
Python
import re
import requests
def extract_challenge_params(url):
"""Extract Cloudflare doğrulama akışı 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);
CaptchaAI ile tek çağrıda çözme
Elle ayıklama teşhis için değerlidir; üretimde ise akışı tümüyle devretmek daha sürdürülebilirdir. CaptchaAI doğrulama sayfasını yükler, JavaScript'i yürütür, proof-of-work'ü çözer ve izin token'ını döndürür. Size kalan tek iş görevi gönderip sonucu sorgulamaktır — örnek, her 5 saniyede bir res.php'yi yoklar:
Fiyatlandırma thread tabanlıdır: BASIC ($15/ay, 5 thread) ilk entegrasyon için yeterli, hacim arttıkça ADVANCE ($90/ay, 50 thread) gibi planlara geçersiniz. TL dalgalansa da aylık maliyet USD üzerinden öngörülebilir kalır.
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_cloudflare_challenge(target_url):
"""Solve Cloudflare doğrulama akışı 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")
Doğrulama başarısızlıklarını ayıklama
Akış koptuğunda belirti genellikle şu noktalardan birine işaret eder:
| Kırılma noktası | Belirti | Olası neden |
|---|---|---|
| Doğrulama sayfası yüklenmiyor | Zaman aşımı veya boş yanıt | Ağ/proxy sorunu |
| Betik yürütülemiyor | Doğrulama döngüye giriyor | Eksik JavaScript API'leri |
| Proof-of-work tamamlanmıyor | Sonsuz dönen simge | Hesaplama zaman aşımı |
| Yanıt reddediliyor | Doğrulamaya geri yönlendirme | Zamanlama ihlali veya profil uyuşmazlığı |
| qa_session_cookie ayarlanmıyor | Çözümden sonra çerez yok | Yanıt ayrıştırma hatası |
| qa_session_cookie reddediliyor | Sonraki istekte 403 | IP veya UA uyuşmazlığı |
Adım adım hata ayıklama
def debug_challenge_flow(url, qa_session_cookie_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 qa_session_cookie
if qa_session_cookie_cookie:
session = requests.Session()
session.cookies.set("qa_session_cookie", qa_session_cookie_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": "qa_session_cookie rejected",
"possible_causes": [
"Cookie expired",
"IP address changed",
"User-Agent mismatch",
"Cookie from different domain",
],
})
return steps
Sık karşılaşılan sorunlar ve çözümleri
| Belirti | Neden | Çözüm |
|---|---|---|
| Tip "managed" ama çözüm başarısız | Doğrulama JS değil Turnstile istiyor |
cloudflare_challenge yerine turnstile yöntemini deneyin |
| qa_session_cookie bir kez çalışıp sonra reddediliyor | IP rotasyonu IP'nizi değiştirdi | Çerez ömrü boyunca IP'yi sabit tutun |
| "Just a moment..." sayfası hiç çözülmüyor | JavaScript engellenmiş veya bozuk | Elle çözüm yerine CaptchaAI kullanın |
| Her istekten sonra doğrulama yeniden çıkıyor | qa_session_cookie gönderilmiyor | Çerezleri oturumda kalıcı tutun |
| Farklı yollarda farklı doğrulama | Yola özel WAF kuralları | Her yolu ayrı ayrı çözün |
Sık sorulan sorular
cloudflare_challenge yöntemi ne zaman turnstile'dan farklıdır?
cloudflare_challenge, JavaScript proof-of-work gerektiren tam sayfa doğrulaması (Just a moment... sayfası) içindir. Sayfada gömülü bir Cloudflare Turnstile widget'ı görüyorsanız turnstile yöntemini kullanın. cType managed olduğu halde çözüm başarısızsa doğrulama Turnstile'a düşmüş olabilir.
qa_session_cookie ikinci istekte neden 403 döndürür?
Neredeyse her zaman IP veya User-Agent uyuşmazlığından. Çerez, çözümü yapan IP'ye ve UA'ya bağlıdır; farklı bir çıkıştan veya farklı UA ile gönderilen istekte geçersiz sayılır. Çözüm ve sonraki istekler için aynı oturumu ve IP'yi kullanın.
Bu doğrulamayı JavaScript çalıştırmadan çözebilir miyim?
Hayır. Proof-of-work ve tarayıcı sinyalleri yalnızca JavaScript yürütülerek hesaplanır; salt HTTP isteğiyle üretilemez. CaptchaAI bunu gerçek tarayıcılarla çalıştırır.
Doğrulama her istekte yeniden çıkıyorsa ne yapmalıyım?
Genellikle qa_session_cookie sonraki isteklere eklenmiyordur. İstemcinizin çerezleri kalıcı tuttuğundan emin olun; requests.Session ya da eşdeğeri kullanın. Çerez süresi (15 dakika–24 saat) dolduğunda yeni doğrulama beklemek normaldir.
Özet
Cloudflare doğrulama sayfaları; ray, doğrulama betikleri, _cf_chl_opt nesnesi ve form alanları üzerinden proof-of-work token akışını yürütür. Akış, IP'ye ve User-Agent'a bağlı, 15 dakika–24 saat geçerli bir qa_session_cookie çerezi üretir. CaptchaAI bu parametreleri elle ayrıştırma yükünü kaldırır; çözücü akışın tamamını yönetir. Hata ayıklarken parametreleri tanımak, akışın nerede koptuğunu gösterir.