Ketika satu halaman memuat reCAPTCHA v2 dan v3 sekaligus, urutan penanganannya sederhana: selesaikan v3 lebih dulu, lalu tangani v2 hanya jika skor v3 rendah dan situs memunculkan challenge fallback. Bagian yang sulit bukan solving-nya, melainkan mendeteksi versi mana yang aktif dan sitekey mana untuk masing-masing versi. Salah pasang sitekey, dan token langsung ditolak.
Secara ringkas, alur penanganannya terdiri dari tiga langkah:
- Deteksi apakah halaman benar-benar memuat dua versi dan ambil kedua sitekey.
- Selesaikan v3 lebih dulu, karena berjalan otomatis di background.
- Tangani v2 hanya jika respons server menunjukkan fallback terpicu.
Artikel ini membahas tiap langkah tersebut, lengkap dengan strategi solving dan kasus edge yang sering bikin skrip otomasi gagal diam-diam.
Kenapa satu halaman memakai v2 dan v3 sekaligus
User visits page
↓
reCAPTCHA v3 runs invisibly in background
↓
Score returned to server (e.g., 0.4)
↓
Score below threshold (e.g., < 0.7)?
├─ YES → Show reCAPTCHA v2 checkbox/image challenge
└─ NO → Allow action without visible CAPTCHA
Kombinasi ini memberi operator situs dua lapisan sekaligus:
- Mayoritas pengunjung dengan skor v3 tinggi tidak pernah melihat CAPTCHA, sehingga gesekan tetap rendah.
- Traffic mencurigakan dengan skor v3 rendah baru dihadapkan ke challenge v2 sebagai lapisan keamanan cadangan.
- Operator situs memegang kendali penuh atas threshold yang memisahkan mode invisible dan mode visible.
Untuk otomasi, konsekuensinya jelas: Anda tidak bisa mengasumsikan satu versi saja. Skrip harus siap menghadapi keduanya. Perbedaan mendasar antara kedua versi merangkum kenapa keduanya butuh perlakuan berbeda:
| Aspek | reCAPTCHA v3 | reCAPTCHA v2 |
|---|---|---|
| Mode | Invisible, skor di background | Visible, checkbox atau image |
| Lokasi sitekey | Parameter render= di URL script |
Atribut data-sitekey pada widget |
| Kapan muncul | Selalu berjalan lebih dulu | Hanya saat skor v3 di bawah threshold |
| Field token | g-recaptcha-response |
g-recaptcha-response |
Tiga pola implementasi ganda yang umum
Pola 1: pre-assessment v3 dengan fallback v2
Pola paling sering ditemui, dengan dua karakteristik utama:
- v3 dieksekusi lebih dulu secara otomatis.
- v2 baru dirender kalau skor v3 berada di bawah ambang.
<!-- Both scripts loaded -->
<script src="https://www.google.com/recaptcha/api.js?render=V3_SITE_KEY"></script>
<script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
<form id="loginForm">
<!-- v2 widget (hidden initially) -->
<div id="recaptcha-v2-container" style="display:none;">
<div class="g-recaptcha" data-sitekey="V2_SITE_KEY"></div>
</div>
<button type="submit">Login</button>
</form>
<script>
// First attempt: v3 invisible
grecaptcha.ready(function() {
grecaptcha.execute('V3_SITE_KEY', {action: 'login'}).then(function(v3Token) {
fetch('/api/verify-v3', {
method: 'POST',
body: JSON.stringify({token: v3Token})
})
.then(r => r.json())
.then(data => {
if (data.score < 0.7) {
// Score too low → show v2 fallback
document.getElementById('recaptcha-v2-container').style.display = 'block';
grecaptcha.render('recaptcha-v2-container', {sitekey: 'V2_SITE_KEY'});
} else {
// Score OK → submit form directly
document.getElementById('loginForm').submit();
}
});
});
});
</script>
Pola 2: sitekey berbeda untuk aksi berbeda
Homepage → v3 only (passive score)
Login page → v3 assessment, v2 fallback
Checkout → v2 always (high security)
Contact form → v3 only
Peta di atas menggambarkan situs yang memakai v3 untuk pemantauan pasif dan menyimpan v2 khusus untuk aksi berisiko tinggi seperti checkout. Versi CAPTCHA yang Anda hadapi bisa berubah tergantung halaman.
Pola 3: satu script untuk dua mode
<script src="https://www.google.com/recaptcha/api.js?render=V3_SITE_KEY"></script>
<script>
// v3 execute
grecaptcha.execute('V3_SITE_KEY', {action: 'login'});
// v2 render (uses a different site key)
grecaptcha.render('v2-container', {sitekey: 'V2_SITE_KEY'});
</script>
Satu script reCAPTCHA bisa menangani v2 dan v3 sekaligus, tetapi render dan execute tetap memakai dua sitekey berbeda.
Mendeteksi halaman reCAPTCHA ganda
Sebelum memilih strategi, pastikan dulu halaman memang memuat dua versi. Ada tiga penanda yang perlu Anda cek pada HTML halaman:
- Sitekey v3 pada parameter
render=di URL script atau di panggilangrecaptcha.execute(). - Sitekey v2 pada atribut
data-sitekeydi widget, atau pada panggilangrecaptcha.render(). - Status ganda: kedua sitekey ada dan nilainya berbeda.
Deteksi dengan Python
import requests
import re
def detect_dual_recaptcha(url):
"""Detect if a page uses both reCAPTCHA v2 and v3."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
}
html = requests.get(url, headers=headers, timeout=15).text
result = {
"has_v3": False,
"has_v2": False,
"v3_site_key": None,
"v2_site_key": None,
"dual": False,
"pattern": None,
}
# Detect v3 (render parameter or enterprise.execute)
v3_match = re.search(r"api\.js\?render=([A-Za-z0-9_-]+)", html)
if v3_match and v3_match.group(1) != "explicit":
result["has_v3"] = True
result["v3_site_key"] = v3_match.group(1)
# Detect v3 in execute calls
v3_execute = re.search(
r"grecaptcha\.(?:enterprise\.)?execute\s*\(\s*['\"]([^'\"]+)['\"]",
html,
)
if v3_execute:
result["has_v3"] = True
if not result["v3_site_key"]:
result["v3_site_key"] = v3_execute.group(1)
# Detect v2 (g-recaptcha class or explicit render)
v2_match = re.search(r'data-sitekey="([^"]+)"', html)
if v2_match:
key = v2_match.group(1)
if key != result.get("v3_site_key"):
result["has_v2"] = True
result["v2_site_key"] = key
# Check for explicit v2 render
v2_render = re.search(
r"grecaptcha\.render\s*\([^,]+,\s*\{[^}]*sitekey:\s*['\"]([^'\"]+)",
html,
)
if v2_render:
result["has_v2"] = True
if not result["v2_site_key"]:
result["v2_site_key"] = v2_render.group(1)
result["dual"] = result["has_v3"] and result["has_v2"]
if result["dual"]:
# Determine pattern
if "display:none" in html or "display: none" in html:
result["pattern"] = "v3_pre_assessment_v2_fallback"
else:
result["pattern"] = "v2_v3_simultaneous"
return result
detection = detect_dual_recaptcha("https://staging.example.com/qa-login")
print(detection)
Deteksi dengan Node.js
const axios = require("axios");
async function detectDualRecaptcha(url) {
const { data: html } = await axios.get(url, { timeout: 15000 });
const result = {
hasV3: false,
hasV2: false,
v3SiteKey: null,
v2SiteKey: null,
dual: false,
};
// v3 detection
const v3Match = html.match(/api\.js\?render=([A-Za-z0-9_-]+)/);
if (v3Match && v3Match[1] !== "explicit") {
result.hasV3 = true;
result.v3SiteKey = v3Match[1];
}
// v2 detection
const v2Match = html.match(/data-sitekey="([^"]+)"/);
if (v2Match && v2Match[1] !== result.v3SiteKey) {
result.hasV2 = true;
result.v2SiteKey = v2Match[1];
}
result.dual = result.hasV3 && result.hasV2;
return result;
}
detectDualRecaptcha("https://staging.example.com/qa-login").then(console.log);
Strategi menyelesaikan reCAPTCHA ganda
Ada tiga pendekatan yang lazim dipakai, tergantung seberapa sering situs menurunkan fallback v2 ke traffic Anda:
- Selesaikan v3 dulu, tangani v2 hanya saat fallback muncul — paling efisien untuk mayoritas kasus.
- Lewati v3, langsung selesaikan v2 — untuk situs yang selalu menantang traffic otomasi.
- Serahkan keputusan ke browser — untuk implementasi yang sulit diprediksi dari HTML mentah.
Strategi 1: selesaikan v3 dulu, v2 hanya jika perlu
Strategi paling efisien meniru alur situs itu sendiri: coba v3, dan panggil v2 hanya saat fallback benar-benar terpicu.
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_v3(site_key, page_url, action="login"):
"""Solve reCAPTCHA v3 and return token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"version": "v3",
"action": action,
"json": 1,
}).json()
task_id = submit["request"]
for _ in range(60):
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.get("status") == 1:
return result["request"]
raise TimeoutError("v3 solve timeout")
def solve_v2(site_key, page_url):
"""Solve reCAPTCHA v2 and return token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1,
}).json()
task_id = submit["request"]
for _ in range(60):
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.get("status") == 1:
return result["request"]
raise TimeoutError("v2 solve timeout")
def solve_dual_recaptcha(v3_key, v2_key, page_url, action="login"):
"""Handle dual reCAPTCHA: try v3, fall back to v2."""
# Step 1: Try v3
v3_token = solve_v3(v3_key, page_url, action)
# Step 2: Submit v3 token to target
response = requests.post(f"{page_url}/verify", data={
"g-recaptcha-response": v3_token,
})
# Step 3: Check if v2 fallback is needed
if "recaptcha" in response.text.lower() and v2_key:
print("v3 score too low — v2 fallback triggered")
v2_token = solve_v2(v2_key, page_url)
return {"version": "v2", "token": v2_token}
return {"version": "v3", "token": v3_token}
result = solve_dual_recaptcha(
v3_key="6LcExample_v3_key",
v2_key="6LcExample_v2_key",
page_url="https://staging.example.com/qa-login",
)
print(f"Solved with {result['version']}")
Beberapa hal penting dari kode di atas:
- Kedua fungsi memakai
methodyang sama, yaituuserrecaptcha. - Yang membedakan hanyalah parameter
versiondan sitekey. - Token hasilnya sama-sama masuk ke field
g-recaptcha-response.
Strategi 2: lewati v3, langsung selesaikan v2
# If you consistently fail v3 assessment, just solve v2 directly
token = solve_v2(v2_site_key, page_url)
submit_form(token)
Jika Anda tahu situs selalu menampilkan v2 untuk traffic otomasi (skor v3-nya pasti rendah), tidak ada gunanya membayar solve v3. Langsung selesaikan v2 seperti di atas — ini menghemat satu langkah yang kemungkinan besar sia-sia.
Strategi 3: penanganan lewat browser
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")
time.sleep(3)
# Check if v2 widget is visible
v2_visible = driver.execute_script("""
const container = document.querySelector('.g-recaptcha');
if (!container) return false;
const style = window.getComputedStyle(container.parentElement);
return style.display !== 'none' && style.visibility !== 'hidden';
""")
if v2_visible:
# v2 is showing — solve v2
sitekey = driver.find_element(
By.CSS_SELECTOR, "[data-sitekey]"
).get_attribute("data-sitekey")
token = solve_v2(sitekey, driver.current_url)
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
else:
# v3 only — solve v3
# Extract v3 key from page source
v3_key = driver.execute_script(
"return document.querySelector('script[src*=\"render=\"]')"
".src.match(/render=([^&]+)/)[1];"
)
token = solve_v3(v3_key, driver.current_url)
# Inject v3 token into the form
driver.execute_script(f"""
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'g-recaptcha-response';
input.value = '{token}';
document.querySelector('form').appendChild(input);
""")
driver.find_element(By.CSS_SELECTOR, "form").submit()
Untuk implementasi rumit, biarkan browser yang memutuskan versi mana yang aktif, lalu inject token sesuai kondisi.
Contoh skenario untuk tim otomasi di Indonesia
Bayangkan tim data di sebuah startup Jakarta yang menjalankan pipeline pemantauan harga dengan worker di region AWS ap-southeast-3 (Jakarta). Halaman login yang dihadapi memakai v3 di background dan menurunkan challenge v2 saat request datang dari IP pusat data. Pola paling hemat di sini adalah Strategi 1: coba v3 dulu, dan hanya bayar solve v2 saat fallback muncul. Dengan model harga CaptchaAI berbasis thread — misalnya BASIC ($15/bulan, 5 threads) dengan solve tak terbatas per thread — percobaan v3 yang kadang gagal threshold tidak menambah tagihan. Catatan kepatuhan lokal: sesuai UU Pelindungan Data Pribadi (UU 27/2022), proses hanya data yang berhak Anda akses dan hindari data pribadi tanpa dasar yang sah.
Kasus edge yang sering muncul
Dua sitekey berbeda dalam satu halaman
Situs dengan reCAPTCHA ganda selalu punya DUA sitekey berbeda — satu untuk v3, satu untuk v2:
- Sitekey v3 muncul di URL script
?render=KEYdan digrecaptcha.execute('KEY', ...). - Sitekey v2 ada di
data-sitekey="KEY"pada div widget. - Memakai sitekey yang salah untuk versi yang salah menghasilkan token tidak valid, dan situs menolaknya tanpa pesan error yang jelas.
reCAPTCHA Enterprise dengan fallback v2
# Detect and handle Enterprise + v2 combo
if "recaptcha/enterprise.js" in html:
# Use enterprise parameter for v3
v3_params = {"enterprise": 1, "version": "v3"}
else:
v3_params = {"version": "v3"}
Sebagian implementasi Enterprise memakai v3 Enterprise untuk scoring dan v2 biasa untuk challenge, dideteksi lewat keberadaan recaptcha/enterprise.js.
Beberapa form dalam satu halaman
# Target the login form specifically
login_form = soup.find("form", id="login-form")
widget = login_form.find(attrs={"data-sitekey": True})
sitekey = widget["data-sitekey"]
Jika satu halaman memuat beberapa form (misalnya login dan registrasi), tiap form bisa punya instance reCAPTCHA sendiri. Ambil sitekey dari form spesifik yang Anda targetkan seperti di atas, jangan yang pertama ditemukan.
Pertanyaan umum
Berapa biaya menyelesaikan reCAPTCHA ganda dengan CaptchaAI?
CaptchaAI menagih per thread, bukan per solve, dengan solve tak terbatas per thread setiap bulan. Paket BASIC ($15/bulan, 5 threads) sudah cukup untuk banyak alur otomasi, dan karena tidak ada biaya per CAPTCHA, percobaan v3 yang gagal threshold sebelum fallback v2 tidak menambah tagihan.
Bagaimana urutan solve yang benar untuk v2 dan v3?
Selesaikan v3 lebih dulu karena berjalan otomatis. Jika skornya lolos threshold situs, tidak ada v2 yang muncul dan pekerjaan selesai. Anda baru menyelesaikan v2 saat respons server menunjukkan fallback terpicu.
Apakah satu API call bisa menangani v2 dan v3 sekaligus?
Tidak. v2 dan v3 adalah tipe terpisah dengan sitekey dan parameter berbeda, jadi masing-masing butuh call tersendiri. Namun dalam praktik Anda sering hanya butuh satu call bila v3 lolos tanpa memicu v2.
Bagaimana cara tahu fallback v2 sudah terpicu?
Periksa respons server setelah token v3 dikirim. Jika respons memuat HTML widget v2 atau memicu challenge (redirect maupun respons AJAX berisi HTML CAPTCHA), fallback aktif. Di browser, cek apakah container v2 berubah menjadi visible setelah submit v3.
Apakah CaptchaAI mendukung reCAPTCHA Enterprise pada halaman ganda?
Ya. reCAPTCHA v2 Enterprise dan v3 Enterprise sama-sama didukung. Tambahkan parameter enterprise saat men-submit, dan tangani fallback v2 dengan cara yang sama seperti implementasi non-Enterprise.
Ringkasan
Implementasi reCAPTCHA ganda memakai v3 untuk pre-assessment invisible dan v2 sebagai fallback visible saat skor v3 terlalu rendah. Deteksi kedua versi dengan memeriksa parameter render (v3) dan atribut data-sitekey pada widget (v2). Strategi otomasi paling efisien: selesaikan v3 lebih dulu dengan CaptchaAI, kirim token, dan tangani v2 hanya jika fallback terpicu. Ingat, tiap versi butuh API call terpisah dengan sitekey masing-masing.
Artikel terkait
- Menangani reCAPTCHA di single-page application dinamis
- Cara menyelesaikan reCAPTCHA v2 callback via API
- Menangani reCAPTCHA v2 dan Turnstile di situs yang sama