Ada tiga hal yang memisahkan scraper Anda dari data di balik reCAPTCHA v2: sitekey yang tertanam di halaman, satu panggilan API untuk menyelesaikan challenge itu, dan token hasil yang di-inject kembali ke halaman. Selesaikan ketiganya secara program, dan pipeline scraping Anda berjalan terus tanpa ada checkbox atau image grid yang harus diklik manusia.
Prinsipnya sederhana: jangan minta bot Anda "berpura-pura jadi manusia" di depan CAPTCHA. Rutekan challenge ke CaptchaAI, biarkan diselesaikan di infrastruktur mereka, lalu pakai token yang kembali. Panduan ini menunjukkan alur penuh dengan kode siap pakai untuk Python (Selenium + requests) dan Node.js (Puppeteer), plus pendekatan HTTP saja tanpa browser sama sekali.
Dua parameter yang menggerakkan seluruh alur
Setiap widget reCAPTCHA v2 hanya butuh dua nilai dari sisi scraper Anda:
googlekey— sitekey publik yang tertanam di HTML halaman. Anda menemukannya pada atributdata-sitekeydi elemen.g-recaptcha, atau dengan mencari string6L...di sumber halaman.pageurl— URL persis tempat CAPTCHA muncul.
Empat langkah membentuk kerangka yang sama di setiap contoh di bawah:
- Kirim kedua parameter ke API CaptchaAI.
- Simpan task ID yang dikembalikan.
- Polling hasil sampai statusnya selesai.
- Pakai token dengan meng-inject-nya ke field
g-recaptcha-response, atau memanggil callback function widget.
Setelah itu backend situs target memverifikasi token ke Google dan meloloskan request Anda seperti request dari pengguna biasa.
Poin penting: token yang dihasilkan terikat ke pasangan sitekey + URL tadi, sekali pakai, dan kedaluwarsa cepat. Jadi Anda menyelesaikan CAPTCHA sedekat mungkin dengan momen halaman itu benar-benar Anda submit — bukan menyimpannya untuk nanti.
Python: Selenium + CaptchaAI
Pendekatan pertama memakai browser sungguhan. Selenium membuka halaman, Anda tarik sitekey dari DOM, kirim ke API, polling hasilnya, lalu inject token dan submit form dari dalam browser yang sama.
import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# Step 1: Open the page with Selenium
driver = webdriver.Chrome()
driver.get("https://example.com/protected-page")
# Step 2: Extract the sitekey
sitekey = driver.find_element(By.CSS_SELECTOR, ".g-recaptcha").get_attribute("data-sitekey")
page_url = driver.current_url
# Step 3: Submit to CaptchaAI
response = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": 1
}).json()
task_id = response["request"]
# Step 4: Poll for result
token = None
for _ in range(40):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id,
"json": 1
}).json()
if result.get("status") == 1:
token = result["request"]
break
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"Solve failed: {result['request']}")
# Step 5: Inject the token and submit
driver.execute_script(
f'document.getElementById("g-recaptcha-response").innerHTML = "{token}";'
)
# Check for callback
callback = driver.execute_script(
'var el = document.querySelector(".g-recaptcha"); '
'return el ? el.getAttribute("data-callback") : null;'
)
if callback:
driver.execute_script(f'{callback}("{token}");')
else:
driver.find_element(By.CSS_SELECTOR, "form").submit()
# Step 6: Scrape the data
print(driver.page_source[:500])
driver.quit()
Perhatikan blok callback di akhir: banyak implementasi reCAPTCHA v2 tidak cukup diisi field g-recaptcha-response saja — situs menunggu callback function dipanggil. Kode di atas mengecek atribut data-callback dan memanggilnya jika ada; kalau tidak ada, ia langsung submit form. Ini pembeda antara token yang "masuk" dan token yang benar-benar diterima situs.
Node.js: Puppeteer + CaptchaAI
Untuk tim yang stack scraping-nya berbasis JavaScript, alur yang sama berjalan di Puppeteer. Strukturnya identik — ekstrak sitekey, kirim, polling, inject — hanya idiomatis Node.js.
const puppeteer = require("puppeteer");
async function scrapeWithCaptcha(url) {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto(url, { waitUntil: "networkidle2" });
// Extract sitekey
const sitekey = await page.$eval(".g-recaptcha", (el) => el.dataset.sitekey);
// Submit to CaptchaAI
const submitRes = await fetch(
`https://ocr.captchaai.com/in.php?${new URLSearchParams({
key: "YOUR_API_KEY",
method: "userrecaptcha",
googlekey: sitekey,
pageurl: url,
json: 1,
})}`
);
const { request: taskId } = await submitRes.json();
// Poll for result
let token;
for (let i = 0; i < 40; i++) {
await new Promise((r) => setTimeout(r, 5000));
const res = await fetch(
`https://ocr.captchaai.com/res.php?${new URLSearchParams({
key: "YOUR_API_KEY",
action: "get",
id: taskId,
json: 1,
})}`
);
const data = await res.json();
if (data.status === 1) {
token = data.request;
break;
}
if (data.request !== "CAPCHA_NOT_READY")
throw new Error(`Solve failed: ${data.request}`);
}
// Inject token
await page.evaluate((t) => {
document.getElementById("g-recaptcha-response").innerHTML = t;
const cb = document.querySelector(".g-recaptcha")?.dataset.callback;
if (cb && window[cb]) window[cb](t);
}, token);
// Wait for navigation after form submit
await page.waitForNavigation({ waitUntil: "networkidle2" });
const content = await page.content();
await browser.close();
return content;
}
scrapeWithCaptcha("https://example.com/protected-page").then(console.log);
Loop polling di kedua contoh memberi jeda 5 detik antar cek dan berhenti setelah 40 percobaan. Angka ini masuk akal karena satu solve reCAPTCHA v2 umumnya rampung dalam 15–60 detik; menaikkan batas iterasi hanya perlu jika Anda beroperasi pada jam sibuk dengan antrean panjang.
Kapan mode headless justru jadi penghalang
Sebagian situs menandai headless browser dan memblokirnya bahkan sebelum reCAPTCHA sempat tampil — jadi masalahnya bukan di CAPTCHA-nya, melainkan di cara halaman dibuka. Jika Anda kena blok lebih awal:
- Pakai
headless: "new"di Puppeteer (mode standar yang lebih baru dan lebih mirip Chrome biasa). - Kurangi sinyal browser otomatis lewat konfigurasi Chromium standar, bukan flag debug yang ganjil.
- Set string User-Agent yang wajar dan konsisten dengan versi Chrome yang Anda tiru.
- Pertimbangkan rotasi egress jaringan yang diotorisasi berdampingan dengan solve CaptchaAI Anda.
Kalau reCAPTCHA sudah muncul dan bisa Anda tarik sitekey-nya, blokir awal bukan lagi persoalan — Anda tinggal menyelesaikan challenge dan lanjut.
Lewati browser sepenuhnya: pendekatan HTTP saja
Kalau situs target menerima CAPTCHA dalam alur form submission biasa, Anda tidak perlu browser sama sekali. Pendekatan HTTP murni ini jauh lebih ringan: satu requests.Session, sitekey yang sudah Anda tahu, dan POST akhir yang membawa g-recaptcha-response.
import requests
import time
session = requests.Session()
session.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0"
# Load the page to get cookies
session.get("https://example.com/protected-page")
# Solve the CAPTCHA
sitekey = "6Le-wvkSAAAAAN..." # extracted from page HTML
solve_resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY", "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": "https://example.com/protected-page",
"json": 1
}).json()
task_id = solve_resp["request"]
time.sleep(15)
# Poll
for _ in range(30):
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id, "json": 1
}).json()
if result.get("status") == 1:
token = result["request"]
break
time.sleep(5)
# Submit with token
resp = session.post("https://example.com/protected-page", data={
"g-recaptcha-response": token,
"other_field": "value"
})
print(resp.text[:500])
Jalur HTTP ini paling hemat sumber daya untuk scraping volume besar karena tidak ada browser yang perlu di-render per halaman. Dua hal yang perlu Anda pertimbangkan:
- Ia hanya bekerja bila situs memverifikasi token murni di sisi server.
- Jika token harus dipasang lewat JavaScript widget (misalnya callback yang memicu request internal), Anda tetap butuh Selenium atau Puppeteer.
Menskalakan solve untuk scraping volume tinggi
Satu solve butuh 15–60 detik, jadi menjalankannya berurutan akan menghambat pipeline. Untuk agensi price-monitoring atau tim data yang memantau ratusan halaman katalog, kuncinya adalah paralelisme: CaptchaAI memproses beberapa task bersamaan, dan jumlah solve serentak dibatasi oleh alokasi thread paket Anda, bukan oleh biaya per solve.
Model tagihannya per thread dengan solve tak terbatas per thread selama sebulan — tidak ada biaya per-CAPTCHA, sehingga biaya tetap terprediksi saat trafik scraping melonjak. Cocokkan jumlah thread dengan konkurensi pipeline Anda:
| Paket | Harga/bulan | Thread | Cocok untuk |
|---|---|---|---|
| BASIC | $15 | 5 | crawler kecil |
| STANDARD | $30 | 15 | beban menengah |
| ADVANCE | $90 | 50 | puluhan solve serentak |
Kalau latency jadi perhatian, deploy worker scraping Anda dekat dengan target dan dengan endpoint solve. Developer di Indonesia biasanya memilih region seperti:
- AWS
ap-southeast-1(Singapura) — round-trip rendah untuk banyak target regional - AWS
ap-southeast-3(Jakarta) — paling dekat untuk trafik dalam negeri - GCP
asia-southeast2(Jakarta) — alternatif jika stack Anda sudah di GCP
Satu catatan kepatuhan yang relevan secara lokal: di bawah UU Pelindungan Data Pribadi (UU 27/2022), scrape hanya data yang berhak Anda proses dan hindari data pribadi di balik login milik orang lain.
Pertanyaan Umum
Beberapa pertanyaan yang paling sering muncul saat menaruh solve reCAPTCHA v2 ke dalam pipeline scraping produksi.
Berapa thread yang saya butuhkan untuk scraping volume tinggi?
Sebanyak jumlah CAPTCHA yang ingin Anda selesaikan bersamaan. Jika pipeline memproses 15 halaman terlindungi secara paralel, paket 15 thread seperti STANDARD ($30/bulan) sudah pas; naikkan ke ADVANCE ($90/bulan, 50 thread) saat konkurensi bertambah. Solve per thread tidak dibatasi.
Kenapa token saya kadang ditolak situs target?
Dua penyebab paling umum:
- Token sudah kedaluwarsa — masa berlakunya hanya sekitar 2 menit, jadi jangan menyimpannya sebelum submit.
- Situs sebenarnya menunggu callback function dipanggil, bukan sekadar field
g-recaptcha-responseyang terisi.
Pastikan Anda menyelesaikan CAPTCHA tepat sebelum submit, dan panggil callback bila ada — seperti pada contoh Selenium dan Puppeteer di atas.
Bisakah saya menyelesaikan reCAPTCHA v2 tanpa Selenium atau Puppeteer?
Bisa, selama situs menerima g-recaptcha-response sebagai POST field biasa. Pakai pendekatan HTTP saja di atas. Jika token harus dipasang lewat JavaScript widget, Anda tetap memerlukan browser.
Bagaimana menangani solve yang gagal atau kehabisan waktu?
Loop polling di contoh berhenti setelah batas iterasi tercapai. Bungkus langkah solve dengan logika coba ulang: jika API mengembalikan error atau token tak kunjung siap, kirim ulang task lalu ulangi. Pada pipeline besar, alirkan task yang gagal ke antrean terpisah agar satu kegagalan tidak menghambat halaman lain.
Bagaimana jika situs memakai reCAPTCHA Enterprise?
Tambahkan enterprise=1 ke request CaptchaAI Anda. Detailnya ada di panduan solve reCAPTCHA v2 Enterprise.
Panduan Terkait
- Cara solve reCAPTCHA v2 via API
- Menangani CAPTCHA dengan Selenium di Python
- Solve CAPTCHA dengan Puppeteer di Node.js
- Error umum saat solve reCAPTCHA v2