Sorun Giderme

reCAPTCHA v2 ve Cloudflare Turnstilesinin Aynı Sitede Kullanımı

Bazı siteler giriş sayfalarında reCAPTCHA'yı ve ödeme sayfalarında Turnstile'yi kullanır. Diğerleri A/B sağlayıcılar arasında test yapıyor — aynı URL, bir ziyaretçi için reCAPTCHA'yı ve diğeri için Turnstile'yi gösteriyor. Tek bir çözücü yöntemini sabit kodlamak, otomasyonunuzun diğer türle karşılaştığında bozulduğu anlamına gelir.

Siteler Neden Birden Fazla CAPTCHA Sağlayıcısı Kullanıyor?

Senaryo Nasıl Görünüyor?
Farklı sayfalar, farklı sağlayıcılar Giriş = reCAPTCHA, ödeme = Turnstile
A/B test sağlayıcıları Aynı sayfa her iki türü de rastgele gösterir
Taşıma işlemi devam ediyor Eski sayfalarda reCAPTCHA var, yeni sayfalarda Turnstile var
Başarısızlık durumunda geri dönüş Birincil sağlayıcı başarısız oluyor → ikincil sağlayıcıya geri dönüyor
Bölgesel çeşitlilik ABD'li ziyaretçiler için reCAPTCHA, AB için Turnstile (GDPR)

Python: Otomatik Algıla ve Çöz

import requests
import time
import re
from dataclasses import dataclass

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"


@dataclass
class CaptchaInfo:
    provider: str     # "recaptcha" or "turnstile"
    method: str       # API method name
    sitekey: str
    pageurl: str
    response_field: str  # Form field name for the token


def detect_captcha_type(html, pageurl):
    """
    Detect which CAPTCHA provider is on the page.
    Returns CaptchaInfo or None.
    """
    # Check for Turnstile
    turnstile_match = re.search(
        r'class=["\'][^"\']*cf-turnstile[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
        html,
    )
    if not turnstile_match:
        turnstile_match = re.search(
            r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*cf-turnstile',
            html,
        )

    if turnstile_match:
        return CaptchaInfo(
            provider="turnstile",
            method="turnstile",
            sitekey=turnstile_match.group(1),
            pageurl=pageurl,
            response_field="cf-turnstile-response",
        )

    # Check for reCAPTCHA
    recaptcha_match = re.search(
        r'class=["\'][^"\']*g-recaptcha[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
        html,
    )
    if not recaptcha_match:
        recaptcha_match = re.search(
            r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*g-recaptcha',
            html,
        )

    # Also check for script-rendered reCAPTCHA
    if not recaptcha_match:
        recaptcha_match = re.search(
            r'grecaptcha\.render\([^,]+,\s*\{[^}]*["\']sitekey["\']\s*:\s*["\']([^"\']+)["\']',
            html,
        )

    if recaptcha_match:
        return CaptchaInfo(
            provider="recaptcha",
            method="userrecaptcha",
            sitekey=recaptcha_match.group(1),
            pageurl=pageurl,
            response_field="g-recaptcha-response",
        )

    return None


def solve_captcha(info):
    """Solve any detected CAPTCHA type via CaptchaAI."""
    params = {
        "key": API_KEY,
        "method": info.method,
        "json": 1,
    }

    if info.method == "userrecaptcha":
        params["googlekey"] = info.sitekey
        params["pageurl"] = info.pageurl
    elif info.method == "turnstile":
        params["sitekey"] = info.sitekey
        params["pageurl"] = info.pageurl

    resp = requests.post(SUBMIT_URL, data=params, timeout=30).json()
    if resp.get("status") != 1:
        raise RuntimeError(f"Submit failed: {resp.get('request')}")

    task_id = resp["request"]
    for _ in range(60):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve failed: {poll.get('request')}")

    raise RuntimeError("Timeout")


def process_page(session, url):
    """Fetch page, detect CAPTCHA type, solve, and return form-ready data."""
    response = session.get(url)
    captcha_info = detect_captcha_type(response.text, url)

    if not captcha_info:
        print(f"No CAPTCHA detected on {url}")
        return None

    print(f"Detected {captcha_info.provider} on {url}")
    print(f"  Sitekey: {captcha_info.sitekey[:30]}...")

    token = solve_captcha(captcha_info)
    print(f"  Solved: {token[:30]}...")

    return {
        "provider": captcha_info.provider,
        "response_field": captcha_info.response_field,
        "token": token,
    }


# Usage: Handle multiple pages with different providers
session = requests.Session()

pages = [
    "https://staging.example.com/qa-login",      # Might have reCAPTCHA
    "https://example.com/checkout",   # Might have Turnstile
]

for url in pages:
    result = process_page(session, url)
    if result:
        form_data = {result["response_field"]: result["token"]}
        # Add other form fields...
        # session.post(url, data=form_data)

JavaScript: Dinamik CAPTCHA Algılama

const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";

function detectCaptchaType(html, pageurl) {
  // Turnstile
  const turnstileMatch = html.match(/cf-turnstile[^>]*data-sitekey=["']([^"']+)["']/);
  if (turnstileMatch) {
    return { provider: "turnstile", method: "turnstile", sitekey: turnstileMatch[1], pageurl, field: "cf-turnstile-response" };
  }

  // reCAPTCHA
  const recaptchaMatch = html.match(/g-recaptcha[^>]*data-sitekey=["']([^"']+)["']/);
  if (recaptchaMatch) {
    return { provider: "recaptcha", method: "userrecaptcha", sitekey: recaptchaMatch[1], pageurl, field: "g-recaptcha-response" };
  }

  // Script-rendered reCAPTCHA
  const scriptMatch = html.match(/sitekey["']\s*:\s*["']([^"']+)["']/);
  if (scriptMatch) {
    return { provider: "recaptcha", method: "userrecaptcha", sitekey: scriptMatch[1], pageurl, field: "g-recaptcha-response" };
  }

  return null;
}

async function solveCaptcha(info) {
  const body = new URLSearchParams({ key: API_KEY, method: info.method, json: "1" });
  if (info.method === "userrecaptcha") { body.set("googlekey", info.sitekey); body.set("pageurl", info.pageurl); }
  else if (info.method === "turnstile") { body.set("sitekey", info.sitekey); body.set("pageurl", info.pageurl); }

  const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
  if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);

  const taskId = resp.request;
  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const poll = await (await fetch(url)).json();
    if (poll.request === "CAPCHA_NOT_READY") continue;
    if (poll.status === 1) return poll.request;
    throw new Error(`Solve: ${poll.request}`);
  }
  throw new Error("Timeout");
}

async function processPage(url) {
  const response = await fetch(url);
  const html = await response.text();
  const info = detectCaptchaType(html, url);

  if (!info) { console.log(`No CAPTCHA on ${url}`); return null; }
  console.log(`${info.provider} detected on ${url}`);

  const token = await solveCaptcha(info);
  return { provider: info.provider, field: info.field, token };
}

// Usage
const pages = ["https://staging.example.com/qa-login", "https://example.com/checkout"];
for (const url of pages) {
  const result = await processPage(url);
  if (result) {
    console.log(`Solved ${result.provider}: ${result.token.substring(0, 30)}...`);
  }
}

Sağlayıcı Tespit Referansı

sağlayıcı HTML İşaretleyici Komut dosyası URL'si Yanıt Alanı
reCAPTCHA v2 class="g-recaptcha" google.com/recaptcha/api.js g-recaptcha-response
Cloudflare Turnstile class="cf-turnstile" challenges.cloudflare.com/turnstile cf-turnstile-response
hCaptcha class="h-captcha" js.hcaptcha.com/1/api.js h-captcha-response

Sorun giderme

Sorun Sebep Düzeltme
Yanlış CAPTCHA türü algılandı Regex yanlış öğeyle eşleşiyor Yalnızca data-sitekey'yi değil, öncelikle sağlayıcıya özel sınıf adlarını kontrol edin
Doğru çözümden sonra jeton reddedildi Yanlış yanıt alanı adı kullanıldı Alan adını sağlayıcıyla eşleştirin: g-recaptcha-response vs cf-turnstile-response
Ziyaretler arasında CAPTCHA türü değişiklikleri A/B testi veya coğrafi tabanlı seçim Her zaman dinamik olarak tespit edin; sağlayıcıyı hiçbir zaman sabit kodlamayın
Her iki sağlayıcı da tek sayfada tespit edildi Biri gizlenmiş olabilir/inactive Öğe görünürlüğünü kontrol edin — yalnızca görünür CAPTCHA'yı çözün
Komut dosyasıyla oluşturulan CAPTCHA'lar için algılama başarısız oluyor Kaynakta HTML işaretçisi yok Komut dosyalarında grecaptcha.render() veya turnstile.render() çağrılarını kontrol edin

SSS

Bir sayfa hem reCAPTCHA'yı hem de Turnstile'yi aynı anda kullanabilir mi?

Nadiren aynı formda olur ancak sitenin farklı kısımlarında gerçekleşir. Her ikisi de bir sayfada görünüyorsa, genellikle yalnızca biri etkindir; hangi widget'in görünür olduğunu ve boş olmayan bir data-sitekey'ye sahip olduğunu kontrol edin.

CaptchaAI her iki sağlayıcı için de aynı API'yi mi kullanıyor?

Aynı uç noktalar (in.php / res.php) ancak farklı method değerleri. reCAPTCHA, googlekey ile method=userrecaptcha'yi kullanırken Turnstile, sitekey ile method=turnstile'yi kullanır. Otomatik algılama modeli bu eşlemeyi yönetir.

Sağlayıcı yük devretme işlemini nasıl halledebilirim?

Bir site oturumun ortasında reCAPTCHA'dan Turnstile'ye geçerse (örneğin, reCAPTCHA yüklenemezse), sağlayıcıyı ilk ziyaretten itibaren önbelleğe almak yerine her sayfa isteğinde CAPTCHA türünü yeniden tespit edin.

İlgili Makaleler

Sonraki Adımlar

Birden fazla CAPTCHA sağlayıcısına sahip siteleri yönetin —CaptchaAI API anahtarınızı alınve otomatik algılamayı uygulayın.

İlgili kılavuzlar:

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