Beberapa situs menerapkan reCAPTCHA v2 dengan callback function alih-alih field tersembunyi g-recaptcha-response standar. Saat Anda solve CAPTCHA dan memasukkan token ke field tersembunyi, tidak ada yang terjadi — halaman mengabaikannya karena situs mengharapkan Anda memanggil JavaScript function dengan token tersebut.
Panduan ini menunjukkan cara mendeteksi reCAPTCHA v2 berbasis callback, solve via API CaptchaAI, dan invoke callback dengan benar. Panggilan API identik dengan reCAPTCHA v2 standar — hanya langkah inject token yang berbeda.
Baru mengenal reCAPTCHA v2? Mulailah dengan Cara Solve reCAPTCHA v2 Menggunakan API untuk alur standar, lalu kembali ke sini untuk varian callback.
Prasyarat
| Item | Detail |
|---|---|
| API key CaptchaAI | Dapatkan dari captchaai.com/api.php. String 32 karakter. |
| URL halaman target | URL lengkap tempat widget reCAPTCHA v2 dimuat. |
| Sitekey reCAPTCHA v2 | Kunci publik yang terkait dengan instance widget. |
| Browser automation tool | Selenium, Puppeteer, atau Playwright — Anda membutuhkan eksekusi JavaScript untuk invoke callback. |
| Nama callback function | Fungsi JavaScript yang diharapkan situs untuk menerima token. |
Cara Mengidentifikasi Implementasi Callback
reCAPTCHA v2 standar menulis token yang diselesaikan ke textarea tersembunyi g-recaptcha-response. Implementasi callback melewati itu dan memanggil JavaScript function secara langsung. Berikut cara membedakannya.
Metode 1: Periksa atribut data-callback
Periksa div widget reCAPTCHA di source halaman:
<div class="g-recaptcha"
data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
data-callback="SubmitToken">
</div>
Jika data-callback ada, situs menggunakan callback. Nilainya (SubmitToken) adalah nama function yang Anda butuhkan.
Metode 2: Periksa panggilan grecaptcha.render()
Cari JavaScript halaman untuk grecaptcha.render:
grecaptcha.render('recaptcha-container', {
sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
callback: userVerified
});
Properti callback memberikan nama function. Dalam hal ini, userVerified.
Metode 3: Periksa konfigurasi reCAPTCHA internal
Buka konsol browser di halaman target dan jalankan:
___grecaptcha_cfg.clients[0]
Navigasikan pohon objek untuk menemukan properti callback. Path pastinya berbeda di setiap situs — mungkin clients[0].aa.l.callback atau lainnya tergantung versi reCAPTCHA dan minifikasinya. Jika halaman memiliki beberapa instance reCAPTCHA, cek clients[1], clients[2], dll.
Script Deteksi Cepat
Jalankan ini di konsol browser untuk menemukan nama callback secara otomatis:
// 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));
});
}
Perbedaan Callback Solve vs v2 Standar
Panggilan API ke CaptchaAI identik. Satu-satunya perbedaan adalah apa yang Anda lakukan dengan token setelah diterima.
| Langkah | v2 Standar | v2 Callback |
|---|---|---|
| 1. Submit ke CaptchaAI | method=userrecaptcha + sitekey + pageurl |
Sama |
| 2. Poll hasil | action=get + captcha ID |
Sama |
| 3. Terima token | Format token sama | Sama |
| 4. Inject token | Set nilai field g-recaptcha-response |
Invoke callback function dengan token |
| 5. Submit form | Trigger form submission | Biasanya otomatis — callback menanganinya |
Penting: Jangan set
g-recaptcha-responsepada implementasi berbasis callback. Halaman mengabaikan field tersebut dan menunggu callback function dipanggil. Set field tanpa invoke callback membuat CAPTCHA tampak belum solved.
Aliran penyelesaian
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
Implementasi Python (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()
Yang dilakukan kode ini:
- Submit sitekey dan pageurl ke
in.phpdenganmethod=userrecaptcha— identik dengan v2 standar. - Poll
res.phpsetiap 5 detik hingga token siap. - Deteksi nama callback function dari DOM halaman.
- Invoke callback function dengan solved token menggunakan
execute_script. - JavaScript situs menangani sisanya — form submission, validasi, atau page redirect.
Implementasi Node.js (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();
})();
Implementasi PHP
Panggilan API sama di PHP. Invoke callback memerlukan browser context, jadi contoh ini hanya mencakup solving sisi server. Gunakan headless browser tool (mis. PHP WebDriver) untuk langkah inject.
<?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);
}
Setelah mendapat token di PHP, gunakan browser automation tool (mis. php-webdriver) untuk eksekusi:
SubmitToken("TOKEN_FROM_CAPTCHAAI");
Error Umum
| # | Error | Apa yang terjadi | Solusi |
|---|---|---|---|
| 1 | Set g-recaptcha-response bukan invoke callback |
Halaman mengabaikan token — form tidak pernah di-submit | Temukan nama callback dan invoke dengan token |
| 2 | Nama callback function salah | JavaScript error: function tidak didefinisikan | Cek ulang data-callback, grecaptcha.render(), atau konfigurasi internal |
| 3 | Callback ada di client index yang berbeda | Instance reCAPTCHA salah ditargetkan di halaman multi-widget | Cek ___grecaptcha_cfg.clients[1], clients[2], dll. |
| 4 | Invoke callback sebelum halaman siap | Function belum didefinisikan dalam page context | Tunggu DOMContentLoaded atau networkidle sebelum invoke |
| 5 | Menggunakan nama yang ter-minify/obfuscate | Nama callback di source rusak | Gunakan runtime browser console untuk menemukan referensi function aslinya |
| 6 | Mencampur v2 callback dengan invisible v2 | Beberapa implementasi invisible juga menggunakan callback | Cek apakah data-size="invisible" ada — jika ya, lihat Cara Solve reCAPTCHA Invisible Menggunakan API |
Pemecahan Masalah
Token solved tapi halaman tidak bereaksi
Penyebab paling umum: Anda set g-recaptcha-response alih-alih invoke callback. Cek apakah widget memiliki data-callback atau callback di grecaptcha.render(). Jika ya, Anda harus menjalankan function tersebut.
ReferenceError: SubmitToken is not defined
Callback function belum dimuat atau namanya salah. Coba:
- Konfirmasi nama dengan cek
data-callbackatau konfigurasi internal. - Tunggu halaman fully loaded sebelum eksekusi.
- Di situs yang di-minify, function mungkin ditetapkan ke variabel — cek
window.SubmitTokendi konsol.
Token berfungsi di v2 standar tapi gagal di halaman ini
Anda mungkin menghadapi implementasi callback. Ikuti langkah deteksi di atas untuk konfirmasi, lalu beralih ke invoke callback.
ERROR_BAD_TOKEN_OR_PAGEURL
Pasangan sitekey/pageurl tidak valid. Ini error API, tidak terkait callback vs standar. Ekstrak ulang kedua nilai dari halaman.
Halaman memiliki beberapa widget reCAPTCHA
Setiap widget mungkin memiliki callbacknya sendiri. Cek setiap div g-recaptcha atau periksa ___grecaptcha_cfg.clients untuk semua instance yang terdaftar. Cocokkan widget dengan form yang Anda targetkan.
ERROR_CAPTCHA_UNSOLVABLE
Challenge tidak dapat diselesaikan. Coba lagi dengan request baru. Ini tidak spesifik untuk callback.
Untuk referensi error lengkap, lihat Error Solve reCAPTCHA v2 yang Umum.
Mengapa CaptchaAI Berfungsi untuk Ini
| Faktor | Detail |
|---|---|
| Panggilan API yang sama | Alur submit/poll identik dengan reCAPTCHA v2 standar — tidak ada parameter tambahan yang diperlukan |
| Success rate | 99,5%+ untuk reCAPTCHA v2 (callback dan standar menggunakan solver yang sama) |
| Kecepatan solve | Di bawah 60 detik |
| Kompatibilitas token | Token yang dikembalikan berfungsi dengan inject g-recaptcha-response maupun invoke callback |
| Harga | Paket berbasis thread mulai $15/bulan untuk solve tanpa batas |
Token yang dikembalikan CaptchaAI tetap sama terlepas dari cara situs mengimplementasikan reCAPTCHA v2. Perbedaannya sepenuhnya ada pada kode sisi klien — cara Anda mengirim token ke halaman.
Contoh lengkap yang dapat dijalankan
Butuh proyek kerja lengkap dengan pengaturan lingkungan, polling, percobaan ulang, dan penanganan kesalahan?
Lihat contoh lengkap yang dapat dijalankan di GitHub →
Pertanyaan Umum
Apa itu callback reCAPTCHA v2?
Callback adalah JavaScript function yang didaftarkan situs untuk menerima solved reCAPTCHA token. Daripada menulis token ke field tersembunyi g-recaptcha-response, reCAPTCHA memanggil function tersebut secara langsung. Function ini biasanya memicu form submission, validasi, atau page redirect.
Apa perbedaan callback dari reCAPTCHA v2 standar untuk API call?
Tidak ada perbedaan sama sekali. Anda mengirim request method=userrecaptcha yang sama dengan sitekey dan pageurl yang sama. Satu-satunya perbedaan adalah apa yang Anda lakukan dengan token setelah diterima — Anda invoke callback function alih-alih set nilai field.
Bagaimana menemukan nama callback function?
Tiga tempat untuk dicek: (1) atribut data-callback pada div reCAPTCHA, (2) properti callback dalam panggilan grecaptcha.render() di JavaScript halaman, (3) objek ___grecaptcha_cfg.clients[0] di browser console — navigasikan pohon untuk menemukan properti callback.
Bisakah saya menggunakan token dengan kedua metode?
Token itu sendiri berfungsi baik. Namun jika situs mengharapkan callback, set g-recaptcha-response akan diabaikan. Selalu sesuaikan metode inject dengan yang diharapkan situs.
Apakah saya perlu browser untuk invoke callback?
Ya. Callback adalah JavaScript function dalam page context. Anda memerlukan Selenium, Puppeteer, Playwright, atau tool serupa yang dapat menjalankan JavaScript di halaman target.
Mulai Solve Callback reCAPTCHA v2
- Dapatkan API key — captchaai.com/api.php
- Deteksi nama callback — cek
data-callback,grecaptcha.render(), atau konfigurasi internal - Salin kode Python atau Node.js di atas — ganti placeholder dengan key, sitekey, pageurl, dan callback name Anda
- Jalankan — token tiba dalam waktu kurang dari 60 detik, panggilan balik diaktifkan, dan halaman memproses hasilnya
- Terjebak? Mulailah denganKesalahan Penyelesaian reCAPTCHA v2 yang Umumatau baca selengkapnyadokumen API CaptchaAI
Artikel Terkait
- Selesaikan Recaptcha Python Tak Terlihat
- Penanganan Situs yang Sama Cloudflare Turnstile Recaptcha V2
- Penyelaman Mendalam Api Penilaian Perusahaan Recaptcha