Token'ı çözdünüz, g-recaptcha-response alanına yazdınız ama sayfa hiç tepki vermiyor. Sorun token'da değil: bu sayfa reCAPTCHA v2'yi bir callback fonksiyonu (geri çağırma) ile çalıştırıyor ve çözülmüş token'ı gizli alana değil, doğrudan bir JavaScript fonksiyonuna iletmenizi bekliyor. Türkiye'deki e-ticaret ve fintech ekiplerinde bu, staging.example.com/qa-login gibi bir QA ortamında giriş ya da ödeme formunu otomatik test ederken sık karşılaşılan bir durumdur — token doğru olsa bile callback tetiklenmediği için form gönderilmez.
Bu rehberde callback tabanlı reCAPTCHA v2'yi nasıl tanıyacağınızı, CaptchaAI API ile nasıl çözeceğinizi ve callback'i doğru şekilde nasıl tetikleyeceğinizi göreceksiniz. API çağrısı standart reCAPTCHA v2 ile birebir aynı; yalnızca token'ı sayfaya iletme adımı değişiyor.
reCAPTCHA v2 tarafında yeni misiniz? Önce standart akış için API ile reCAPTCHA v2 çözme rehberine göz atın, sonra callback çeşidi için buraya dönün.
Callback çözümü standart v2'den nerede ayrılıyor?
İşe koyulmadan önce şunu netleştirelim: callback, çözüm mantığını değil, yalnızca son adımı değiştirir. CaptchaAI'ye giden API çağrısı birebir aynı; fark, token'ı aldıktan sonra onu sayfaya nasıl ilettiğinizde başlıyor.
| Adım | Standart v2 | Callback v2 |
|---|---|---|
| 1. CaptchaAI'ye gönderme | method=userrecaptcha + sitekey + pageurl |
Aynı |
| 2. Sonucu sorgulama | action=get + captcha ID |
Aynı |
| 3. Token'ı alma | Aynı token formatı | Aynı |
| 4. Token'ı iletme | g-recaptcha-response alan değerini ayarlayın |
Token'ı callback fonksiyonuna geçirin |
| 5. Formu gönderme | Form gönderimini tetikleyin | Genellikle otomatik; callback bunu kendisi halleder |
Kritik: Callback tabanlı uygulamalarda
g-recaptcha-responsealanını ayarlamayın. Sayfa bu alanı yok sayar ve callback fonksiyonunun tetiklenmesini bekler. Callback'i çağırmadan yalnızca alanı doldurursanız, CAPTCHA hiç çözülmemiş gibi görünür.
Callback uygulamasını nasıl tanırsınız
Standart reCAPTCHA v2, çözülmüş token'ı gizli bir g-recaptcha-response textarea alanına yazar. Callback uygulamaları bu adımı atlar ve doğrudan bir JavaScript fonksiyonunu çağırır. Hedef sayfanın hangisini kullandığını üç yöntemle anlayabilirsiniz.
Yöntem 1: data-callback özniteliğine bakın
Sayfa kaynağında reCAPTCHA widget div'ini inceleyin:
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
data-callback="SubmitToken">
</div>
data-callback varsa site bir callback kullanıyordur. Buradaki değer (SubmitToken) ihtiyacınız olan fonksiyon adıdır.
Yöntem 2: grecaptcha.render() çağrılarına bakın
Sayfanın JavaScript'i içinde grecaptcha.render çağrısını arayın:
grecaptcha.render('recaptcha-container', {
sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
callback: userVerified
});
callback özelliği fonksiyonu belirtir — bu örnekte userVerified.
Yöntem 3: Dahili reCAPTCHA yapılandırmasına bakın
Hedef sayfada tarayıcı konsolunu açın ve şunu çalıştırın:
___grecaptcha_cfg.clients[0]
Nesne ağacında gezinerek callback özelliğini bulun. Tam yol siteye göre değişir; reCAPTCHA sürümüne ve minify durumuna göre clients[0].aa.l.callback ya da bambaşka bir yol olabilir. Sayfada birden çok reCAPTCHA örneği varsa clients[1], clients[2] gibi indeksleri de kontrol edin.
Callback adını otomatik bulan kısa script
Callback adlarını tek seferde bulmak için şunu tarayıcı konsolunda çalıştırın:
// Check data-callback attributes
document.querySelectorAll('[data-callback]').forEach(el => {
console.log('data-callback:', el.getAttribute('data-callback'));
});
// Check internal config
if (typeof ___grecaptcha_cfg !== 'undefined') {
Object.keys(___grecaptcha_cfg.clients).forEach(key => {
const client = ___grecaptcha_cfg.clients[key];
console.log(`Client ${key}:`, JSON.stringify(client, null, 2));
});
}
Başlamadan önce elinizde ne olmalı
Callback'i tespit ettiğinize göre, çözümü çalıştırmadan önce şu beş parçayı hazır edin:
| Gereksinim | Ayrıntılar |
|---|---|
| CaptchaAI API anahtarı | captchaai.com/api.php üzerinden alın. 32 karakterlik bir dizedir. |
| Hedef sayfa URL'si | reCAPTCHA v2 widget'ının yüklendiği tam URL. |
reCAPTCHA v2 sitekey |
Widget örneğine bağlı açık anahtar. |
| Tarayıcı otomasyon aracı | Selenium, Puppeteer veya Playwright — callback'i tetiklemek için JavaScript çalıştırmanız gerekir. |
| Callback fonksiyonu adı | Sitenin token'ı iletmenizi beklediği JavaScript fonksiyonu. |
Çözüm akışı
Uçtan uca akış şöyle işler: sayfadan değerleri çıkarın, CaptchaAI'ye gönderin, token'ı sorgulayın ve callback'i çağırın.
Page → extract sitekey + pageurl + callback name
↓
POST to in.php (method=userrecaptcha)
↓
receive captcha ID
↓
wait 15–20 seconds
↓
GET res.php (action=get, id=…)
↓ ↓
CAPCHA_NOT_READY status=1 → token
(wait 5s, retry) ↓
invoke callback(token)
↓
site processes token automatically
Python ile uygulama (Selenium)
import time
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
PAGE_URL = "https://staging.example.com/qa-login"
CALLBACK_NAME = "SubmitToken" # The callback function name from the page
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def solve_recaptcha_v2(api_key, sitekey, pageurl):
"""Submit a reCAPTCHA v2 task and return the solved token."""
# Step 1: Submit the captcha
submit_resp = requests.post(
SUBMIT_URL,
data={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
},
timeout=30,
)
submit_resp.raise_for_status()
submit_data = submit_resp.json()
if submit_data.get("status") != 1:
raise RuntimeError(f"Submit failed: {submit_data}")
captcha_id = submit_data["request"]
print(f"Task created — captcha ID: {captcha_id}")
# Step 2: Wait before first poll
time.sleep(15)
# Step 3: Poll for result
for _ in range(60):
result_resp = requests.get(
RESULT_URL,
params={
"key": api_key,
"action": "get",
"id": captcha_id,
"json": 1,
},
timeout=30,
)
result_resp.raise_for_status()
result_data = result_resp.json()
if result_data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result_data.get("status") == 1:
return result_data["request"]
raise RuntimeError(f"Polling error: {result_data}")
raise TimeoutError("reCAPTCHA v2 solve timed out")
def detect_callback_name(driver):
"""Detect the reCAPTCHA callback function name from the page."""
# Try data-callback attribute first
callback = driver.execute_script("""
const el = document.querySelector('[data-callback]');
if (el) return el.getAttribute('data-callback');
return null;
""")
if callback:
return callback
# Try internal reCAPTCHA config
callback = driver.execute_script("""
if (typeof ___grecaptcha_cfg === 'undefined') return null;
const clients = ___grecaptcha_cfg.clients;
for (const key of Object.keys(clients)) {
const client = clients[key];
// Walk the object tree to find a callback function
const json = JSON.stringify(client);
const match = json.match(/"callback":"(\\w+)"/);
if (match) return match[1];
}
return null;
""")
return callback
# Main workflow
driver = webdriver.Chrome()
driver.get(PAGE_URL)
# Detect the callback name (or use the known name)
detected = detect_callback_name(driver)
callback_name = detected or CALLBACK_NAME
print(f"Using callback: {callback_name}")
# Solve the CAPTCHA
token = solve_recaptcha_v2(API_KEY, SITEKEY, PAGE_URL)
print(f"Solved token: {token[:80]}...")
# Invoke the callback with the token
driver.execute_script(f"{callback_name}(arguments[0]);", token)
print("Callback invoked — site should process the token automatically")
# Wait for the page to process
time.sleep(3)
driver.quit()
Kod ne yapıyor:
sitekeyvepageurldeğerlerinimethod=userrecaptchailein.php'ye gönderir — standart v2 ile aynı adım.- Token hazır olana kadar
res.php'yi 5 saniyede bir sorgular. - Callback fonksiyonu adını sayfanın DOM'undan tespit eder.
execute_scriptile çözülmüş token'ı callback fonksiyonuna geçirir.- Gerisini sitenin kendi JavaScript'i halleder — form gönderimi, doğrulama veya yönlendirme.
Node.js ile uygulama (Puppeteer)
const puppeteer = require("puppeteer");
const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
const PAGE_URL = "https://staging.example.com/qa-login";
const CALLBACK_NAME = "SubmitToken";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function solveRecaptchaV2(apiKey, sitekey, pageurl) {
// Step 1: Submit the captcha
const submitResp = await fetch(SUBMIT_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
key: apiKey,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
json: "1",
}),
});
const submitData = await submitResp.json();
if (submitData.status !== 1) {
throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
}
const captchaId = submitData.request;
console.log(`Task created — captcha ID: ${captchaId}`);
// Step 2: Wait before first poll
await sleep(15_000);
// Step 3: Poll for result
for (let i = 0; i < 60; i++) {
const resultResp = await fetch(
`${RESULT_URL}?${new URLSearchParams({
key: apiKey,
action: "get",
id: captchaId,
json: "1",
})}`
);
const resultData = await resultResp.json();
if (resultData.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (resultData.status === 1) {
return resultData.request;
}
throw new Error(`Polling error: ${JSON.stringify(resultData)}`);
}
throw new Error("reCAPTCHA v2 solve timed out");
}
async function detectCallbackName(page) {
return page.evaluate(() => {
// Try data-callback attribute
const el = document.querySelector("[data-callback]");
if (el) return el.getAttribute("data-callback");
// Try internal config
if (typeof ___grecaptcha_cfg !== "undefined") {
const clients = ___grecaptcha_cfg.clients;
for (const key of Object.keys(clients)) {
const json = JSON.stringify(clients[key]);
const match = json.match(/"callback":"(\w+)"/);
if (match) return match[1];
}
}
return null;
});
}
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto(PAGE_URL, { waitUntil: "networkidle2" });
// Detect callback
const detected = await detectCallbackName(page);
const callbackName = detected || CALLBACK_NAME;
console.log(`Using callback: ${callbackName}`);
// Solve the CAPTCHA
const token = await solveRecaptchaV2(API_KEY, SITEKEY, PAGE_URL);
console.log(`Solved token: ${token.slice(0, 80)}...`);
// Invoke the callback
await page.evaluate(
(name, tkn) => {
window[name](tkn);
},
callbackName,
token
);
console.log("Callback invoked — site should process the token automatically");
await sleep(3_000);
await browser.close();
})();
PHP ile uygulama
API çağrısı PHP'de de aynı. Callback'i çağırmak bir tarayıcı bağlamı gerektirdiğinden, bu örnek yalnızca sunucu tarafındaki çözüm adımını kapsar. Token'ı sayfaya iletmek için headless bir tarayıcı aracı (örneğin PHP WebDriver) kullanın.
<?php
$apiKey = "YOUR_CAPTCHAAI_API_KEY";
$sitekey = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
$pageurl = "https://staging.example.com/qa-login";
// Step 1: Submit
$submit = file_get_contents("https://ocr.captchaai.com/in.php?" . http_build_query([
"key" => $apiKey,
"method" => "userrecaptcha",
"googlekey" => $sitekey,
"pageurl" => $pageurl,
"json" => 1,
]));
$submitData = json_decode($submit, true);
if ($submitData["status"] !== 1) {
die("Submit failed: " . $submit);
}
$captchaId = $submitData["request"];
echo "Task created — captcha ID: $captchaId\n";
// Step 2: Wait and poll
sleep(15);
for ($i = 0; $i < 60; $i++) {
$result = file_get_contents("https://ocr.captchaai.com/res.php?" . http_build_query([
"key" => $apiKey,
"action" => "get",
"id" => $captchaId,
"json" => 1,
]));
$resultData = json_decode($result, true);
if ($resultData["request"] === "CAPCHA_NOT_READY") {
sleep(5);
continue;
}
if ($resultData["status"] === 1) {
$token = $resultData["request"];
echo "Solved token: " . substr($token, 0, 80) . "...\n";
// Pass $token to your browser automation to invoke the callback
break;
}
die("Polling error: " . $result);
}
Token'ı PHP tarafında aldıktan sonra, callback'i çağırmak için bir tarayıcı otomasyon aracı (örneğin php-webdriver) kullanın:
SubmitToken("TOKEN_FROM_CAPTCHAAI");
Sık yapılan hatalar
| # | Hata | Ne olur? | Çözüm |
|---|---|---|---|
| 1 | Callback'i çağırmak yerine g-recaptcha-response'yi ayarlamak |
Sayfa token'ı yok sayar; form hiç gönderilmez | Callback adını bulun ve token'ı ona geçirin |
| 2 | Yanlış callback fonksiyonu adı | JavaScript hatası: fonksiyon tanımlı değil | data-callback, grecaptcha.render() veya dahili yapılandırmayı yeniden kontrol edin |
| 3 | Callback farklı bir client indeksinde | Çok widget'lı sayfalarda yanlış reCAPTCHA örneği hedeflenir | ___grecaptcha_cfg.clients[1], clients[2] gibi indeksleri kontrol edin |
| 4 | Callback'i sayfa hazır olmadan çağırmak | Fonksiyon henüz sayfa bağlamında tanımlı değil | Çağırmadan önce DOMContentLoaded veya networkidle durumunu bekleyin |
| 5 | Minify edilmiş/karışık bir ad kullanmak | Kaynaktaki callback adı okunaksız hale gelmiş | Gerçek fonksiyon referansını çalışma zamanında tarayıcı konsolundan bulun |
| 6 | Callback v2'yi görünmez v2 ile karıştırmak | Bazı görünmez uygulamalar da callback kullanır | data-size="invisible" var mı bakın — varsa API ile görünmez reCAPTCHA çözme rehberine göz atın |
Sorun giderme
Callback akışında en sık karşılaşılan durumlar ve hızlı çözümleri aşağıdaki tabloda:
| Belirti / hata | Olası neden ve çözüm |
|---|---|
| Token çözüldü ama sayfa tepki vermiyor | Büyük olasılıkla callback'i çağırmak yerine g-recaptcha-response alanını ayarladınız. Widget'ta data-callback özniteliği ya da grecaptcha.render() içinde callback var mı bakın; varsa o fonksiyonu çağırın. |
ReferenceError: SubmitToken is not defined |
Callback fonksiyonu henüz yüklenmemiş ya da adı yanlış. Adı data-callback veya dahili yapılandırmadan doğrulayın, sayfanın tamamen yüklenmesini bekleyin; minify edilmiş sitelerde window.SubmitToken değerini kontrol edin. |
| Token standart v2'de çalışıyor ama bu sayfada işe yaramıyor | Muhtemelen bir callback uygulamasıyla karşı karşıyasınız. Yukarıdaki tanıma adımlarını izleyip callback çağrısına geçin. |
ERROR_BAD_TOKEN_OR_PAGEURL |
sitekey/pageurl çifti geçersiz — callback ya da standart uygulama ile ilgisi yok. Her iki değeri de sayfadan yeniden çıkarın. |
| Sayfada birden çok reCAPTCHA widget'ı var | Her widget'ın kendi callback'i olabilir. ___grecaptcha_cfg.clients içindeki tüm örnekleri inceleyip doğru widget'ı hedeflediğiniz formla eşleştirin. |
ERROR_CAPTCHA_UNSOLVABLE |
Bu CAPTCHA örneği çözülemedi; yeni bir istekle yeniden deneyin. Bu durum callback'e özgü değildir. |
Hataların tam listesi için yaygın reCAPTCHA v2 çözüm hataları rehberine bakın.
Sık sorulan sorular
Callback fonksiyonunun adını hiç bulamıyorsam ne yapmalıyım?
data-callback ve grecaptcha.render() sonuç vermezse, tarayıcı konsolunda ___grecaptcha_cfg.clients[0] nesnesini açıp callback özelliğini arayın. Ad minify edilmişse, çalışma zamanındaki gerçek fonksiyon referansını window üzerinden kontrol edin.
Callback tabanlı reCAPTCHA v2 çözümü ne kadar sürer?
Çözüm süresi standart v2 ile aynıdır: genellikle 60 saniyenin altında. Callback yalnızca token'ı sayfaya iletme biçimini değiştirir, çözüm hızını değil.
CaptchaAI hCaptcha veya FunCaptcha'yı da çözer mi?
Hayır. CaptchaAI reCAPTCHA v2/v3, Cloudflare Turnstile ve Challenge, GeeTest v3, görüntü/OCR, grid ve BLS türlerini çözer; hCaptcha ve FunCaptcha (Arkose Labs) desteklenmez. GeeTest v4 için destek çok yakında; CaptchaFox, Friendly Captcha ve Lemin ise beta olarak sunulur.
Callback varken yine de g-recaptcha-response alanını doldurabilir miyim?
Token teknik olarak her iki yöntemle de geçerlidir, ancak site bir callback bekliyorsa doldurduğunuz alan yok sayılır. Enjeksiyon yöntemini her zaman sitenin beklentisine göre seçin.
Callback'i Playwright ile de çağırabilir miyim?
Evet. Callback sayfa bağlamında çalışan bir JavaScript fonksiyonu olduğundan, Selenium, Puppeteer veya Playwright gibi sayfada JavaScript çalıştırabilen herhangi bir araç işinizi görür.
Bu senaryoda neden CaptchaAI?
| Faktör | Detay |
|---|---|
| Aynı API çağrısı | Gönder/sorgula akışı standart reCAPTCHA v2 ile aynı; ekstra parametre gerekmez |
| Başarı oranı | reCAPTCHA v2'de desteklenen türlerde yüksek başarı oranı (callback ve standart aynı çözücüyü kullanır) |
| Çözüm süresi | Genellikle 60 saniyenin altında |
| Token uyumluluğu | Dönen token hem g-recaptcha-response enjeksiyonu hem de callback çağrısıyla çalışır |
| Fiyatlandırma | BASIC ($15/ay, 5 thread) planından başlayan, thread tabanlı ve sınırsız çözümlü planlar |
CaptchaAI'nin döndürdüğü token, sitenin reCAPTCHA v2'yi nasıl uyguladığından bağımsız olarak aynıdır. Fark tamamen sizin istemci tarafı kodunuzda: token'ı sayfaya nasıl ilettiğinizde.
Tam çalıştırılabilir örnek
Ortam kurulumu, sorgulama, yeniden denemeler ve hata yönetimini içeren eksiksiz bir çalışan projeye mi ihtiyacınız var?
GitHub'daki tam çalışan örneğe göz atın →
Hemen başlayın: callback'li reCAPTCHA v2 çözümü
- API anahtarınızı alın — captchaai.com/api.php
- Callback adını tespit edin —
data-callback,grecaptcha.render()veya dahili yapılandırmayı kontrol edin - Yukarıdaki Python veya Node.js kodunu kopyalayın — yer tutucuları API anahtarınız,
sitekey,pageurlve callback adınızla değiştirin - Çalıştırın — token 60 saniyenin altında gelir, callback tetiklenir ve sayfa sonucu işler
- Takıldınız mı? Yaygın reCAPTCHA v2 çözüm hataları rehberiyle başlayın veya CaptchaAI API belgelerini okuyun
İlgili Makaleler
- Python ile görünmez reCAPTCHA çözme
- Aynı sayfada reCAPTCHA v2 ve Turnstile yönetimi
- reCAPTCHA Enterprise Assessment API incelemesi