Explainers

Cloudflare WAF Kuralları CAPTCHA'yı Neden Tetikler?

Dün sorunsuz çalışan bir sayfada otomasyonunuz bugün aniden bir Cloudflare doğrulaması görüyorsa, sebep neredeyse her zaman tektir: isteğiniz bir WAF kuralına takıldı. Cloudflare'in Web Uygulaması Güvenlik Duvarı (WAF), site operatörlerinin şu özelliklere göre CAPTCHA tetikleyen kurallar tanımlamasına izin verir:

  • Bot puanı
  • Ülke
  • URL yolu (/login, /api/)
  • HTTP başlıkları
  • İstek oranı

Hangi kuralın devreye girdiğini yanıttan okuyabilirseniz, hem neden doğrulama gördüğünüzü teşhis eder hem de doğru çözüm yöntemini seçersiniz.

CAPTCHA üreten WAF eylemleri

Cloudflare WAF kuralları birden fazla eylemi destekler. Bunlardan yalnızca üçü çözülebilir bir doğrulama önünüze koyar; geri kalanı isteği ya geçirir ya da engeller.

WAF eylemi Ne olur HTTP durumu CaptchaAI yöntemi
Managed Challenge Cloudflare karar verir: görünmez geçiş, Turnstile ya da JS doğrulaması 503 turnstile
JS Challenge 5 saniyelik JavaScript doğrulama sayfası 503 cloudflare_challenge
Interactive Challenge Klasik CAPTCHA (eski, kullanımdan kaldırıldı) 403 turnstile
Block Sert 403, doğrulama yok 403 Yok (çözülemez)
Allow İstek geçer, kontrol yok 200 Yok
Skip Kalan WAF kurallarını uygulamaz 200 Yok
Log Olayı kaydeder, eylem yok 200 Yok

Managed Challenge nasıl karar verir

Managed Challenge, en sık gördüğünüz eylemdir. Türü ziyaretçi başına uyarlanabilir seçer:

WAF rule matches → Managed Challenge triggered
    ↓
Cloudflare evaluates visitor:
  ├─ Low risk → Invisible pass (no visible challenge)
  ├─ Medium risk → Turnstile widget (click to verify)
  └─ High risk → JavaScript challenge page
    ↓
Successful → qa_session_cookie cookie issued

Aynı kural düşük riskte hiç görünmezken yüksek riskte tam JavaScript sayfası açabilir; "bazen çözüm çıkıyor, bazen çıkmıyor" davranışı bu yüzden normaldir.

Otomasyonu en çok tetikleyen WAF kural kalıpları

Kurallar Cloudflare'in ifade diliyle yazılır. En sık karşılaşacağınız kalıplar altı gruba ayrılır. Bot puanı kuralları, otomasyon araçları için en yaygın tetikleyicidir:

# Challenge traffic with low bot scores
(cf.bot_management.score lt 30)
→ Action: Managed Challenge

# Challenge non-verified bots
(cf.bot_management.score lt 50 and not cf.bot_management.verified_bot)
→ Action: JS Challenge

CaptchaAI'nin API çözücüleri gerçek tarayıcılar kullandığından insan seviyesinde puanlar alır. Ülke bazlı kurallar trafiği coğrafyaya göre süzer:

# Challenge traffic from specific countries
(ip.geoip.country in {"CN" "RU" "VN" "IN"})
→ Action: Managed Challenge

# Block specific regions entirely
(ip.geoip.country eq "XX")
→ Action: Block

Yol tabanlı kurallar belirli sayfaları, çoğunlukla oturum ve API uç noktalarını hedefler:

# Challenge login page access
(http.request.uri.path eq "/login" or http.request.uri.path eq "/signup")
→ Action: Managed Challenge

# Challenge API endpoints
(http.request.uri.path contains "/api/")
→ Action: JS Challenge

Orana dayalı kurallar, kısa sürede yükselen istek hacmini yakalar:

# Challenge after high request rate
(cf.threat_score gt 10 and http.request.uri.path contains "/search")
→ Action: Managed Challenge

Başlık tabanlı kurallar, isteğin kimliğine bakar:

# Challenge requests with no Accept-Language header
(not http.request.headers["accept-language"])
→ Action: JS Challenge

# Challenge requests with suspicious UA
(http.user_agent contains "python" or http.user_agent contains "curl")
→ Action: Managed Challenge

Eksik bir Accept-Language başlığı veya python/curl içeren bir User-Agent tek başına doğrulama tetikleyebilir. Son olarak bileşik kurallar birden çok koşulu birleştirir:

# Multiple conditions
(cf.bot_management.score lt 30
 and http.request.uri.path contains "/api/"
 and ip.geoip.country ne "US")
→ Action: JS Challenge

Hangi kuralın tetiklendiğini yanıttan okuma

Bir doğrulama çıktığında, tetikleyen kuralı iki sinyalden okursunuz: durum kodu ve gövde imzaları.

HTTP başlıklarından

import requests

def check_cloudflare_rule_info(url):
    """Extract WAF rule information from Cloudflare doğrulama akışı response."""
    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)

    info = {
        "status": response.status_code,
        "cf_ray": response.headers.get("cf-ray", ""),
        "cf_cache_status": response.headers.get("cf-cache-status", ""),
        "server": response.headers.get("server", ""),
    }

    # Challenge-specific info
    html = response.text

    if response.status_code == 503:
        if "jschl" in html:
            info["challenge_type"] = "JS Challenge (IUAM or WAF rule)"
        elif "challenge-platform" in html:
            info["challenge_type"] = "Managed Challenge"
        elif "cf-turnstile" in html:
            info["challenge_type"] = "Turnstile (Managed Challenge)"

    elif response.status_code == 403:
        if "cf-ray" in str(response.headers):
            info["challenge_type"] = "WAF Block (no challenge)"
        else:
            info["challenge_type"] = "Origin 403 (not Cloudflare)"

    return info

Durum kodu ile gövdedeki imzalar (jschl, challenge-platform, cf-turnstile) birlikte doğrulama türünü ve seçeceğiniz yöntemi belirler.

cf-ray ID'sinden

Her Cloudflare yanıtı bir cf-ray başlığı taşır. Site operatörü bu Ray ID'yi panelde (Security > Events) arayarak hangi kuralın tetiklendiğini görebilir. Sizin tarafınızda cf-ray, yanıtın Cloudflare'den geldiğini doğrular.

Hızlı sorun giderme tablosu

Belirtiden olası kuralı ve doğru yanıtı eşleştirin:

Belirti Olası WAF kuralı Çözüm
Doğrulama yalnızca /login'de çıkıyor Yol tabanlı kural O yol için doğrulamayı çözün
Yalnızca veri merkezi IP'lerinden doğrulama Bot puanı veya IP itibar kuralı Kendi sunucu altyapınızı gözden geçirin veya doğrulamayı çözün
Doğrulama ülkeye göre değişiyor Ülke bazlı kural İzin verilen ülkede proxy kullanın veya doğrulamayı çözün
N istekten sonra doğrulama Orana dayalı kural İstek oranını düşürün veya her doğrulamayı çözün
Her zaman JS doğrulaması (hiç Turnstile yok) JS Challenge eylemi (Managed değil) cloudflare_challenge yöntemini kullanın
Doğrulama olmadan 403 Block eylemi (çözülemez) IP'yi, başlıkları veya istek desenini değiştirin

WAF doğrulamalarını CaptchaAI ile çözme

Çözüm tek bir mantığa iner: Managed Challenge tipik olarak Turnstile olarak render edilir (turnstile), saf JS doğrulaması ise cloudflare_challenge ile çözülür. Her ikisi de CaptchaAI'de tam desteklenen (GA) türlerdir.

Python

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(url, challenge_type):
    """Solve Cloudflare doğrulama akışı based on WAF rule action."""

    if challenge_type == "managed_challenge":
        # Managed Challenge typically renders as Turnstile
        method = "turnstile"
        sitekey = extract_turnstile_sitekey(url)
    elif challenge_type == "js_challenge":
        # JavaScript Challenge page
        method = "cloudflare_challenge"
        sitekey = "managed"
    else:
        raise ValueError(f"Unknown challenge type: {challenge_type}")

    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": method,
        "sitekey": sitekey,
        "pageurl": 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")


def extract_turnstile_sitekey(url):
    """Fetch page and extract Turnstile sitekey."""
    import re
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
    }
    response = requests.get(url, headers=headers, timeout=15)
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', response.text)
    return match.group(1) if match else None

Akış standart CaptchaAI desenidir: görevi in.php'ye gönderin, sonucu res.php ile sorgulayın, dönen token'ı isteğe ekleyin.

Node.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveWAFChallenge(url, challengeType) {
  const method =
    challengeType === "js_challenge" ? "cloudflare_challenge" : "turnstile";
  const sitekey =
    challengeType === "js_challenge" ? "managed" : await extractSitekey(url);

  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method,
      sitekey,
      pageurl: url,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Challenge solve timed out");
}

async function extractSitekey(url) {
  const response = await axios.get(url, {
    headers: {
      "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
    },
  });
  const match = response.data.match(/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/);
  return match ? match[1] : null;
}

WAF kuralları değişince ne olur

Operatörler kuralları sık sık ayarlar ve bu değişiklikler otomasyonunuzu doğrudan etkiler.

Değişiklik Otomasyona etkisi Nasıl tespit edilir
Kural eklendi Çalışan yollarda yeni doğrulama çıkar 503/403 durum değişikliklerini izleyin
Kural kaldırıldı Doğrulama ortadan kalkar Önceden 503 olan yerde artık 200
Eylem sertleşti (Managed → Block) Çözülebilir doğrulama sert bloka döner 503 yerine 403
Eylem yumuşadı (Block → Managed) Sert blok çözülebilir doğrulamaya döner Doğrulama sayfasıyla 503
Eşik değişti (bot puanı 30 → 50) Daha fazla istek doğrulamaya takılır Artan doğrulama sıklığı
Yol kapsamı değişti Farklı URL'ler etkilenir Yeni yollar doğrulamayla döner

Yolları periyodik sorgulayıp durum kodundaki değişimleri yakalamak, kural değişikliğini fark etmenin en pratik yoludur.

import requests
import time

def monitor_cloudflare_protection(urls, interval=3600):
    """Monitor protection changes across URLs."""
    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",
    }

    last_status = {}

    while True:
        for url in urls:
            try:
                response = requests.get(
                    url, headers=headers, timeout=15, allow_redirects=False
                )
                status = response.status_code
                has_challenge = status == 503 or "cf-turnstile" in response.text

                current = {"status": status, "challenge": has_challenge}
                previous = last_status.get(url)

                if previous and current != previous:
                    print(f"[CHANGE] {url}")
                    print(f"  Before: {previous}")
                    print(f"  After:  {current}")

                last_status[url] = current

            except requests.RequestException as e:
                print(f"[ERROR] {url}: {e}")

        time.sleep(interval)

Türkiye'den bir senaryo: ödeme akışı QA testi

Bir e-ticaret ekibinin staging.example.com/qa-checkout ödeme adımını otomatik regresyon testleriyle doğruladığını varsayalım. Staging ortamı canlıyla aynı Cloudflare yapılandırmasını kullandığından, test botu /api/ çağrılarında Managed Challenge alır. İki nokta öne çıkar:

  • KVKK uyumu: Test verileriniz gerçek kişisel veri içeriyorsa KVKK kapsamına girer — akışı izinsiz kazıma değil, yetkili bir QA süreci olarak konumlandırın.
  • Maliyet öngörülebilirliği: CaptchaAI thread bazlı faturalandırır; TL kuru dalgalansa da aylık USD fiyatınız sabittir. BASIC ($15/ay, 5 thread) küçük bir QA paketine yeter.

Sık sorulan sorular

503 mü 403 mü aldığımı anlamak neden önemli?

Çünkü çözülebilirliği belirler. 503 genellikle çözülebilir bir doğrulamadır (Managed veya JS Challenge). Doğrulama sayfası olmadan gelen 403 ise Block eylemidir ve çözülemez.

CaptchaAI hangi Cloudflare doğrulama türlerini çözer?

Cloudflare Turnstile için turnstile, JavaScript tabanlı Cloudflare doğrulama akışı için cloudflare_challenge yöntemini kullanın. İkisi de tam desteklenen türlerdir.

Managed Challenge her zaman Turnstile mı gösterir?

Hayır. Managed Challenge ziyaretçi riskine göre uyarlanır: düşük riskte görünmez geçer, orta riskte Turnstile widget'ı çıkarır, yüksek riskte tam JavaScript sayfası açar.

Doğrulamayı çözdükten sonra çerez ne kadar geçerli olur?

Çözümün ardından qa_session_cookie çerezi, sonraki isteklerin yaklaşık 30 dakika yeniden doğrulama olmadan geçmesine izin verir. Çerez IP'nize ve User-Agent'ınıza bağlıdır.

Cloudflare CAPTCHA otomasyonu KVKK açısından sorun yaratır mı?

Asıl mesele doğrulamayı çözmek değil, topladığınız veridir. Gerçek kişisel veri işliyorsanız KVKK yükümlülükleri devreye girer; CaptchaAI'yi yetkili QA akışları içinde konumlandırın.

Özet

Cloudflare WAF kuralları; bot puanı, ülke, yol, başlık veya istek oranına göre CAPTCHA doğrulaması tetikler. En sık karşılaşacağınız eylem, görünmez geçiş, Turnstile ya da JS doğrulaması olarak uyarlanan Managed Challenge'dır. Tetikleyici kuralı yanıt kodu ve gövde imzalarından okuyun, render edilen türe göre CaptchaAI ile turnstile veya cloudflare_challenge yöntemini seçin. Sert bloklar (403) çözülemez; istek deseninizi veya IP'nizi değiştirin.

İlgili Makaleler

Bu makale için yorumlar devre dışı bırakılmıştır.