Troubleshooting

Tarayıcı Otomasyonu CAPTCHA Başarısız Oluyor Ancak API Çalışıyor: Hata Ayıklama Kılavuzu

Aynı token requests ile sorunsuz çalışıyor ama Selenium içinde forma bıraktığınızda reddediliyorsa, sorun neredeyse hiçbir zaman token'ın kendisi değildir — token'ı sayfaya nasıl enjekte ettiğinizdir. CaptchaAI'den aldığınız değer geçerli, ancak tarayıcı kabul etmiyor. İş genelde üç yerden birinde tıkanır:

  • Yanlış alan seçici — token doğru textarea'ya yazılmıyor, form boş gidiyor.
  • Tetiklenmeyen callback — sayfa token'ı hiç görmüyor, gönder düğmesi pasif kalıyor.
  • Süresi dolan token — çözüm ile gönderim arası çok uzun, değer geçersizleşiyor.

Bu tablo en çok e-ticaret ve fintech QA akışlarında görülür: staging.example.com/qa-login ödeme adımını test ederken token API yanıtında görünüyor ama forma düşmüyordur. Aşağıdaki altı düzeltme bu senaryoların neredeyse tamamını kapsar; belirtinizi yukarıdaki üç maddeden birine oturtup ilgili çözüme geçin.


Tarayıcıda token enjeksiyonu nerede tıkanır?

Önce nedeni daraltın. Beş arıza noktası aşağıda; belirtinize karşılık gelen düzeltmeye geçin.

Sorun Belirti Kök Neden
Token doğru öğeye enjekte edilmedi Form token olmadan gönderiliyor Yanlış textarea seçici
Token gönderilmeden süresi doldu Site CAPTCHA'yı tekrar gösteriyor Çözüm ile gönderim arası çok yavaş
callback tetiklenmedi Gönder düğmesi pasif kalıyor Eksik grecaptcha callback'i
API'ye yanlış pageurl gönderildi Token bu alan adı için geçersiz pageurl uyuşmazlığı
CAPTCHA'nın ötesinde bot algılama Token kabul edildikten sonra engellendi Otomasyon göstergeleri algılandı

Çözüm 1: reCAPTCHA v2 token'ını doğru enjekte edin

En sık yapılan hata, token'ı yalnızca g-recaptcha-response alanına yazıp callback'i unutmaktır. Token hem textarea'ya girmeli hem de callback tetiklenmeli:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time


def inject_recaptcha_token(driver, token):
    """Properly inject reCAPTCHA v2 token in browser."""

    # Step 1: Make the response textarea visible and set the value
    driver.execute_script("""
        // Find all response textareas (may be multiple on page)
        var textareas = document.querySelectorAll('[name="g-recaptcha-response"]');
        textareas.forEach(function(ta) {
            ta.style.display = 'block';
            ta.value = arguments[0];
        });

        // Also set via ID if present
        var byId = document.getElementById('g-recaptcha-response');
        if (byId) {
            byId.style.display = 'block';
            byId.value = arguments[0];
        }
    """, token)

    # Step 2: Trigger the callback
    driver.execute_script("""
        // Try standard callback
        if (typeof ___grecaptcha_cfg !== 'undefined') {
            var clients = ___grecaptcha_cfg.clients;
            for (var key in clients) {
                var client = clients[key];
                // Navigate nested structure to find callback
                for (var prop in client) {
                    var val = client[prop];
                    if (val && typeof val === 'object') {
                        for (var subprop in val) {
                            var subval = val[subprop];
                            if (subval && typeof subval === 'object' && subval.callback) {
                                subval.callback(arguments[0]);
                                return;
                            }
                        }
                    }
                }
            }
        }
        // Fallback: try common callback names
        if (typeof onCaptchaSuccess === 'function') onCaptchaSuccess(arguments[0]);
        else if (typeof captchaCallback === 'function') captchaCallback(arguments[0]);
    """, token)


# Usage
driver = webdriver.Chrome()
driver.get("https://example.com/form")
# ... solve CAPTCHA via CaptchaAI ...
inject_recaptcha_token(driver, token)
time.sleep(1)
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()

Çözüm 2: callback'e bağlı formları yönetin

Bazı formlar, CAPTCHA callback'i tetiklenene kadar gönder düğmesini pasif tutar. Token'ı yazmak yeterli değildir; sayfanın beklediği callback işlevini bulup çağırmanız gerekir. Aşağıdaki kod iki yöntemi sırayla dener:

  • data-callback özniteliği — widget üzerindeki callback adını okuyup doğrudan çağırır. Formların çoğu bunu kullanır.
  • grecaptcha yapılandırması — öznitelik yoksa ___grecaptcha_cfg içinden callback'e ulaşır.
def find_and_trigger_callback(driver, token):
    """Find the reCAPTCHA callback and trigger it."""

    # Method 1: Extract callback from data attribute
    callback_name = driver.execute_script("""
        var widget = document.querySelector('.g-recaptcha');
        if (widget) {
            return widget.getAttribute('data-callback');
        }
        return null;
    """)

    if callback_name:
        driver.execute_script(f"window['{callback_name}'](arguments[0]);", token)
        return True

    # Method 2: Extract from grecaptcha config
    triggered = driver.execute_script("""
        try {
            var widgetId = 0;
            var callback = ___grecaptcha_cfg.clients[widgetId].aa.l.callback;
            if (typeof callback === 'function') {
                callback(arguments[0]);
                return true;
            }
        } catch(e) {}
        return false;
    """, token)

    return triggered

Çözüm 3: zamanlama — çözün ve hemen kullanın

reCAPTCHA v2 token'ları kısa ömürlüdür (genellikle yaklaşık iki dakika). Saniyelerce beklerseniz token göndermeden geçersizleşir ve site CAPTCHA'yı yeniden gösterir. Sonucu aldığınız anda bekletmeden enjekte edin:

import requests
import time


def solve_and_inject_fast(driver, api_key, sitekey, page_url):
    """Solve CAPTCHA and inject token with minimal delay."""
    # Submit solve request
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": api_key,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": page_url,
        "json": 1,
    }, timeout=30)
    task_id = resp.json()["request"]

    # Poll for result
    time.sleep(15)
    for _ in range(24):
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key, "action": "get",
            "id": task_id, "json": 1,
        }, timeout=15)
        data = resp.json()

        if data.get("status") == 1:
            token = data["request"]

            # IMMEDIATELY inject — don't wait
            inject_recaptcha_token(driver, token)

            # Submit form within 5 seconds
            time.sleep(0.5)
            return True

        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(5)

    raise TimeoutError("Solve timeout")

Çözüm 4: SPA ve iframe'lerde doğru pageurl

Token, çözüm isteğinde gönderdiğiniz pageurl için üretilir. SPA'larda veya CAPTCHA iframe içindeyse, başladığınız URL ile tarayıcının şu an bulunduğu URL farklı olabilir. "requests'te çalışıyor ama tarayıcıda başarısız" tablosunun en sinsi nedeni budur. Her zaman driver.current_url değerini temel alın:

def get_correct_pageurl(driver):
    """Get the URL that reCAPTCHA actually sees."""

    # Check if CAPTCHA is in an iframe
    iframes = driver.find_elements(By.TAG_NAME, "iframe")

    for iframe in iframes:
        src = iframe.get_attribute("src") or ""
        if "recaptcha" in src or "anchor" in src:
            # CAPTCHA is in iframe — use parent page URL
            return driver.current_url

    # For SPAs, use current URL (may differ from initial load)
    return driver.current_url


# WRONG — using the URL you navigated to
pageurl = "https://example.com/form"  # May have redirected

# CORRECT — using the URL the browser is actually on
pageurl = get_correct_pageurl(driver)

Çözüm 5: token geçerli ama site otomasyonu engelliyor

Token geçerli olsa bile bazı siteler otomatik tarayıcıları ayrı bir katmanda algılayıp reddeder — bu artık CAPTCHA değil, otomasyon göstergesi sorunudur. Aşağıdaki test profili en yaygın göstergeleri kaldırır:

  • enable-automation anahtarını devre dışı bırakır.
  • Otomasyon uzantısını kapatır.
  • Gerçekçi bir pencere boyutu ayarlar.

Güçlü algılaması olan sitelerde undetected-chromedriver genellikle daha kararlı sonuç verir:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service


def create_stealth_driver():
    """Create a browser that avoids basic bot detection."""
    options = Options()

    # Remove automation indicators
    options.add_argument("--no-sandbox")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option("useAutomationExtension", False)

    # Set realistic window size
    options.add_argument("--window-size=1920,1080")

    driver = webdriver.Chrome(options=options)

    # Override navigator.userAgent
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
    })

    return driver


driver = create_stealth_driver()

Çözüm 6: Turnstile token enjeksiyonu

Cloudflare Turnstile, reCAPTCHA'dan farklı bir alan (cf-turnstile-response) ve farklı bir callback yaklaşımı kullanır; enjeksiyonu buna göre uyarlayın:

def inject_turnstile_token(driver, token):
    """Inject Turnstile token into the page."""
    driver.execute_script("""
        // Find Turnstile response input
        var inputs = document.querySelectorAll(
            'input[name="cf-turnstile-response"], ' +
            'input[name="g-recaptcha-response"]'
        );

        inputs.forEach(function(input) {
            input.value = arguments[0];
        });

        // Trigger change event
        inputs.forEach(function(input) {
            input.dispatchEvent(new Event('change', { bubbles: true }));
            input.dispatchEvent(new Event('input', { bubbles: true }));
        });

        // Try Turnstile callback
        if (window.turnstile) {
            var widgets = document.querySelectorAll('[data-callback]');
            widgets.forEach(function(w) {
                var cb = w.getAttribute('data-callback');
                if (typeof window[cb] === 'function') {
                    window[cb](arguments[0]);
                }
            });
        }
    """, token)

Hata ayıklama kontrol listesi

Sorunu tahminle değil kanıtla daraltın. Aşağıdaki fonksiyon textarea'yı, yazılan değeri, callback'i ve geçerli URL'yi tek seferde raporlar:

def debug_captcha_injection(driver, token):
    """Print debug info to diagnose injection failures."""
    info = driver.execute_script("""
        var result = {};

        // Check textarea exists
        var ta = document.querySelector('[name="g-recaptcha-response"]');
        result.textarea_found = !!ta;
        result.textarea_value_set = ta ? ta.value.length > 0 : false;

        // Check reCAPTCHA loaded
        result.grecaptcha_loaded = typeof grecaptcha !== 'undefined';

        // Check for callback
        var widget = document.querySelector('.g-recaptcha');
        result.has_data_callback = widget ? !!widget.getAttribute('data-callback') : false;
        result.callback_name = widget ? widget.getAttribute('data-callback') : null;

        // Current URL
        result.current_url = window.location.href;

        // Check for errors in console (basic)
        result.has_submit_button = !!document.querySelector('button[type=submit], input[type=submit]');

        return result;
    """)

    for key, value in info.items():
        print(f"  {key}: {value}")

    return info

textarea_value_set false ise Çözüm 1'e, current_url beklediğinizden farklıysa Çözüm 4'e dönün.


Hızlı sorun giderme tablosu

Belirti Neden Çözüm
Token ayarlandı ama form reddediliyor callback tetiklenmedi callback işlevini bulup çağırın
Gönder düğmesi pasif kalıyor Düğmeyi callback etkinleştirir Token enjeksiyonundan sonra callback'i tetikleyin
Gönderimden sonra "Geçersiz CAPTCHA" Token'ın süresi doldu Çözüm ile gönderim arasını kısaltın
Form gönderiminden sonra 403 Bot algılama (CAPTCHA değil) Otomasyon göstergelerini azaltan seçenekleri kullanın
requests'te çalışıyor, tarayıcıda başarısız Farklı pageurl driver.current_url'yi pageurl olarak kullanın

İpucu: Thread tabanlı planlar (BASIC $15/ay, 5 thread) aylık maliyeti USD sabit tutar; kur dalgalansa bile QA bütçeniz öngörülebilir kalır.


Sık sorulan sorular

Token'ı enjekte ettim ama gönder düğmesi hâlâ pasif, neden?

Çünkü çoğu form gönder düğmesini token değeriyle değil, callback tetiklendiğinde etkinleştirir. Token'ı g-recaptcha-response alanına yazdıktan sonra data-callback işlevini de çağırın — Çözüm 2 tam olarak bunu yapar.

Token geçerli olmasına rağmen form neden 403 dönüyor?

Bu genellikle CAPTCHA ile ilgili değildir. Site, otomasyon göstergelerinden veya tutarsız HTTP başlıklarından tarayıcının otomatik olduğunu anlar ve token kabul edilse bile isteği reddeder. Çözüm 5'teki yapılandırma bunu azaltır.

Aynı token'ı birden fazla kez kullanabilir miyim?

Hayır. reCAPTCHA ve Turnstile token'ları tek kullanımlıktır ve yalnızca üretildiği pageurl için geçerlidir. Her gönderim için yeni bir çözüm isteyin.

reCAPTCHA v2 token'ı ne kadar süre geçerli kalır?

Genellikle üretildikten sonra yaklaşık iki dakika. Bu yüzden çözümü aldıktan sonra bekletmeden enjekte edin ve formu birkaç saniye içinde gönderin.

Headless modda token neden daha sık reddediliyor?

Bazı siteler headless tarayıcıları ayrıca işaretler ve geçerli token'ları bile reddedebilir. Önce headful modda doğrulayın, sonra uygun bayraklarla headless'a geçin.


İlgili kılavuzlar



Sonraki adımlar

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