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_cfgiç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-automationanahtarı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
- Selenium ile reCAPTCHA v2 çözücü rehberi
- Token enjeksiyonundan sonra Cloudflare Turnstile 403 hatasını giderme