Explainers

reCAPTCHA v2 callback mekanizması: callback nasıl bulunur ve nasıl tetiklenir?

Geçerli bir token enjekte ettiniz ama gönder düğmesi hâlâ devre dışı mı, form bir türlü gönderilmiyor mu? Eksik parça neredeyse her zaman callback'tir. reCAPTCHA v2'de kullanıcı doğrulamayı tamamladığında Google, sitenin tanımladığı bir JavaScript callback (geri çağırma) fonksiyonunu çalıştırır; bu fonksiyon gönder düğmesini açar, formu doğrular ya da bir AJAX isteği gönderir. CaptchaAI'den aldığınız token'ı textarea'ya yazmak tek başına yetmez — aynı callback'i sizin de tetiklemeniz gerekir, yoksa sayfa CAPTCHA'nın çözüldüğünü fark etmez.


Callback tetiklemeden token neden işe yaramaz?

reCAPTCHA doğrulaması iki katmanlıdır:

  • Ön yüz (tarayıcı): g-recaptcha-response adlı gizli textarea, çözülmüş token ile doldurulur ve callback çalışır.
  • Arka yüz (sunucu): token, Google'ın siteverify uç noktasına sorularak doğrulanır.

Kritik nokta şudur: birçok modern form, textarea dolu olsa bile gönder düğmesini yalnızca callback çalıştığında etkinleştirir veya isteği yalnızca callback'in içinden gönderir.

Yani token teknik olarak doğru olabilir ama callback tetiklenmediyse form akışı hiç başlamaz. Sadece textarea değerini ayarlamak bazı basit sayfalarda yeterli olur; JavaScript'e bağlı akışlarda ise callback'i elle çağırmak, otomasyonun kaçırdığı adımı geri koyar. Bu ayrımı erken görmek, saatlerce süren "token geçerli ama form gitmiyor" hata ayıklamasından kurtarır.


Callback nasıl çalışır?

Site, reCAPTCHA widget'ında callback'i şöyle tanımlar:

<div class="g-recaptcha"
     data-sitekey="6Le-SITEKEY"
     data-callback="onCaptchaSuccess"
     data-expired-callback="onCaptchaExpired">
</div>

<script>
function onCaptchaSuccess(token) {
  document.getElementById('submit-btn').disabled = false;
  document.getElementById('captcha-token').value = token;
}
</script>

Kullanıcı CAPTCHA'yı çözdüğünde Google'ın JavaScript'i onCaptchaSuccess(token)'ı çağırır ve fonksiyon tek argüman olarak token dizesini alır. Mantık basittir: token üretilir, callback çağrılır, form açılır. Otomasyonda bu zincirin ortasındaki adımı atlarsanız geçerli bir token bile boşa gider.


Callback fonksiyonunun adını bulmanın üç yolu

Doğru callback'i tetiklemek için önce adını bilmeniz gerekir. Sitenin kurulumuna göre aşağıdaki üç yöntemden biri sonucu verir; sırayla deneyin:

  • Yöntem 1data-callback özelliğini okuma,
  • Yöntem 2grecaptcha.render() çağrısını sayfa kaynağında arama,
  • Yöntem 3render kaydına araya girip parametreleri yakalama.

Yöntem 1: data-callback özelliğini okuyun

En yaygın durum: callback adı doğrudan widget'ın data-callback özelliğinde durur.

// In browser console
const widget = document.querySelector('.g-recaptcha');
const callbackName = widget?.getAttribute('data-callback');
console.log('Callback:', callbackName);

Yöntem 2: grecaptcha.render çağrısını arayın

Bazı siteler data-callback özelliği yerine callback'i doğrudan grecaptcha.render() seçeneğiyle verir. Sayfa kaynağındaki satır içi script'leri tarayın:

// Search page source for grecaptcha.render
document.querySelectorAll('script:not([src])').forEach(s => {
  if (s.textContent.includes('grecaptcha.render')) {
    console.log(s.textContent.match(/callback\s*:\s*(\w+)/)?.[1]);
  }
});

Yöntem 3: callback kaydını araya girerek yakalayın

Ad ne özellikte ne de kaynakta görünüyorsa, render çağrısını sarmalayıp parametreleri anlık yakalayın. Bunu sayfa yüklenmeden önce DevTools'ta çalıştırın (Kaynaklar → Snippets):

const origRender = grecaptcha.render;
grecaptcha.render = function(container, params) {
  console.log('Render callback:', params.callback);
  console.log('Expired callback:', params['expired-callback']);
  return origRender.apply(this, arguments);
};

Token'ı enjekte edip callback'i tetikleme

Callback adını bulduktan sonra akış dört adıma iner:

  1. sitekey'i sayfadan çıkarın,
  2. token'ı CaptchaAI ile çözün,
  3. token'ı textarea'ya yazın,
  4. callback'i elle çağırın.

Aşağıdaki örnek, bir staging ortamındaki QA giriş formunda bu adımları uçtan uca gösterir.

Python (Selenium)

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

API_KEY = "YOUR_API_KEY"
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")

# Extract sitekey and callback
sitekey = driver.find_element(
    By.CSS_SELECTOR, ".g-recaptcha"
).get_attribute("data-sitekey")

callback = driver.find_element(
    By.CSS_SELECTOR, ".g-recaptcha"
).get_attribute("data-callback")

# Solve with CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": driver.current_url,
    "json": "1",
}).json()
task_id = resp["request"]

token = None
for _ in range(24):
    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["status"] == 1:
        token = result["request"]
        break

# Inject token into textarea
driver.execute_script("""
    document.querySelector('textarea[name="g-recaptcha-response"]').value = arguments[0];
""", token)

# Trigger the callback
if callback:
    driver.execute_script(f"window['{callback}'](arguments[0]);", token)
    print(f"Triggered callback: {callback}")
else:
    # Fallback: try ___grecaptcha_cfg
    driver.execute_script("""
        try {
            var widgetId = Object.keys(___grecaptcha_cfg.clients)[0];
            var callback = ___grecaptcha_cfg.clients[widgetId].aa.l.callback;
            if (typeof callback === 'function') callback(arguments[0]);
        } catch(e) {}
    """, token)
    print("Triggered callback via ___grecaptcha_cfg")

JavaScript (Puppeteer)

const puppeteer = require('puppeteer');

// After solving and getting the token...
await page.evaluate((token, callbackName) => {
  // Set textarea value
  const textarea = document.querySelector(
    'textarea[name="g-recaptcha-response"]'
  );
  textarea.value = token;
  textarea.style.display = 'block'; // sometimes hidden

  // Trigger callback
  if (callbackName && typeof window[callbackName] === 'function') {
    window[callbackName](token);
    console.log(`Called ${callbackName}()`);
  } else {
    // Fallback: search grecaptcha config
    try {
      const clients = ___grecaptcha_cfg.clients;
      const widgetId = Object.keys(clients)[0];
      const cb = clients[widgetId]?.aa?.l?.callback;
      if (typeof cb === 'function') cb(token);
    } catch (e) {}
  }
}, token, callbackName);

Türkiye'de e-ticaret ve fintech ekiplerinin çoğu, ödeme ve giriş akışlarını otomatik regresyon testleriyle doğruluyor. Böyle bir işlem hattında reCAPTCHA korumalı bir formu test ederken token'ı enjekte edip callback'i tetiklemek, testin gerçek kullanıcı davranışını uçtan uca taklit etmesini sağlar. CaptchaAI'nin thread tabanlı planları (BASIC $15/ay, 5 thread'den başlar) bu tür paralel QA çalıştırmalarında USD bazında öngörülebilir bir maliyet sunar.


Görünmez reCAPTCHA'da callback farkı

Görünmez reCAPTCHA v2'de onay kutusu yoktur; doğrulama çoğunlukla bir düğme tıklamasıyla arka planda tetiklenir ve sonuç doğrudan callback'e iletilir. İki varyant arasındaki fark callback açısından belirleyicidir:

Varyant Onay kutusu Callback
Görünür reCAPTCHA v2 Var Genelde var
Görünmez reCAPTCHA v2 Yok Neredeyse zorunlu

Görünmez varyantta callback neredeyse her zaman zorunludur, çünkü token'ı gösterecek görünür bir widget bulunmaz. Görünmez sürümü otomatik test ederken önce callback adını (genelde grecaptcha.render() seçeneklerinden) çıkarın, ardından token'ı enjekte edip callback'i çağırın. İyi haber: görünür ve görünmez varyantların token alanı aynıdır — her ikisinde de g-recaptcha-response textarea'sını doldurursunuz.


data-callback olmayan siteler

Bazı siteler callback kullanmaz; form gönderildiğinde yalnızca grecaptcha.getResponse() değerini kontrol eder. Bu siteler için fonksiyonu geçersiz kılın:

driver.execute_script("""
    const token = arguments[0];
    document.querySelector('textarea[name="g-recaptcha-response"]').value = token;
    // Override getResponse to return the token
    if (typeof grecaptcha !== 'undefined') {
        grecaptcha.getResponse = function() { return token; };
    }
""", token)

# Then submit the form normally
driver.find_element(By.CSS_SELECTOR, "form").submit()

getResponse'u geçersiz kıldığınızda site, sunucuya göndermeden önce token'ı doğrudan bu fonksiyondan okur; böylece görünür bir callback olmasa da form akışı token'ı görür.


Süresi dolan callback'ler (expired-callback)

Bazı siteler, token'ın süresi dolduğunda gönder düğmesini yeniden kilitlemek için data-expired-callback tanımlar. reCAPTCHA token'ları yaklaşık iki dakika geçerlidir; token'ınızın son kullanma anına yaklaştıysanız bu callback tetiklenip formu tekrar kapatabilir. Bunu önlemek için çözümü gönderim anına mümkün olduğunca yaklaştırın.

// Check for expired callback
const expiredCallback = document.querySelector('.g-recaptcha')
  ?.getAttribute('data-expired-callback');
console.log('Expired callback:', expiredCallback);

Çıktı boşsa site bir süre dolumu callback'i tanımlamamıştır. Doluysa, formu yeniden kilitlemesin diye token'ı mümkün olduğunca son anda enjekte edin.


Callback entegrasyonunda kontrol listesi

Callback tabanlı akışları üretim ve QA süreçlerinde kararlı tutmak için birkaç kural işinizi kolaylaştırır:

  • Adı her çalıştırmada dinamik çıkarın. Bazı siteler callback adını sayfa yüklemeleri arasında değiştirir; sabit kodlamak yerine DOM'dan okuyun.
  • Zamanlamaya dikkat edin. Token yaklaşık iki dakika geçerlidir; çözümü gönderime yakın yapın ki expired-callback devreye girmesin.
  • Fallback hazır tutun. data-callback yoksa ___grecaptcha_cfg üzerinden client yapılandırmasındaki fonksiyona ulaşın.
  • Gizli alanları kontrol edin. Bazı temalarda textarea gizlidir; değeri yazmadan önce görünürlüğünü açmanız gerekebilir.
  • Yetki ve KVKK. Bu akışları yalnızca sahibi olduğunuz ya da test yetkiniz bulunan formlarda çalıştırın; toplanan kişisel veriler KVKK kapsamına girer.

Sorun giderme

Aşağıdaki tablo, callback entegrasyonunda en sık karşılaşılan hataları ve çözümlerini özetler:

Sorun Neden Çözüm
Enjeksiyondan sonra form hâlâ devre dışı callback tetiklenmedi callback fonksiyonunu bulup çağırın
ReferenceError: function not defined callback bir closure içinde tanımlı ___grecaptcha_cfg fallback'ini kullanın
Token enjekte edildi ama AJAX gitmedi callback formu değil AJAX'ı tetikliyor callback'in ne yaptığını inceleyin
Token kabul edildi ama sayfa hata veriyor callback'ten önce token'ın süresi doldu Gönderime daha yakın çözün

SSS

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

Yaklaşık iki dakika. Bu yüzden token'ı çözer çözmez enjekte edin ve callback'i hemen tetikleyin; beklerseniz expired-callback devreye girip formu yeniden kilitleyebilir.

window[callbackName] is not a function hatasını neden alıyorum?

callback global kapsamda değil, bir closure içinde tanımlıdır; bu durumda window[...] üzerinden erişemezsiniz. Örneklerdeki ___grecaptcha_cfg fallback'ini kullanarak client yapılandırmasındaki fonksiyona ulaşın.

Sayfada birden fazla reCAPTCHA varsa doğru callback'i nasıl bulurum?

Her widget'ın kendi data-callback değeri vardır. DOM'daki widget'ları tek tek sorgulayın ve her birinin callback adını ayrı ayrı çıkarın; hepsine aynı callback'i uygulamayın.

CaptchaAI reCAPTCHA v2 ve v3'ü destekliyor mu?

Evet, her ikisi de destekleniyor. reCAPTCHA v2'de görünür widget çözülür ve bir token döner; v3'te ise callback yoktur — grecaptcha.execute() bir Promise döndürür ve skor tabanlı token üretir. Yani entegrasyon deseni sürüme göre değişir.


Özet

Callback tabanlı bir reCAPTCHA v2 akışını sağlam kurmanın anahtarı dört noktada toplanır:

  • callback adını DOM'dan dinamik olarak bulun, sabit kodlamayın,
  • token'ı g-recaptcha-response alanına yazın,
  • doğru callback'i (yoksa ___grecaptcha_cfg fallback'ini) çağırın,
  • token'ı gönderime yakın çözerek süre dolumunu önleyin.

Bu dört adımı doğru sıraladığınızda "token geçerli ama form gitmiyor" sorunu ortadan kalkar.


reCAPTCHA v2'yi callback yönetimiyle birlikte çözün

CaptchaAI API anahtarınızı alın, token'ı çözün ve callback'i tek adımda tetikleyin. Örnek kodu kopyalayın, YOUR_API_KEY yerine kendi anahtarınızı koyun ve ilk token'ınızı birkaç dakikada üretin. captchaai.com üzerinden başlayın.


İlgili kılavuzlar

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