GeeTest v3 mengembalikan tiga nilai setelah solve: geetest_challenge, geetest_validate, dan geetest_seccode. Menyuntikkan ketiganya dengan benar ke dalam sesi browser automation memerlukan pemahaman di mana situs mengharapkannya — field form tersembunyi, JavaScript callback, atau XHR payload. Berikut cara melakukannya di setiap framework utama.
Apa yang Anda Suntikkan
CaptchaAI mengembalikan hasil tiga bagian:
{
"geetest_challenge": "a1b2c3d4e5...modified_challenge",
"geetest_validate": "abc123def456_validate",
"geetest_seccode": "abc123def456_validate|jordan"
}
Ketiga nilai tersebut harus disuntikkan. Hilangnya salah satu menyebabkan kegagalan verifikasi.
Langkah 1: Ekstrak Parameter dan Solve
Umum untuk semua framework — ekstrak gt dan challenge, lalu solve dengan CaptchaAI:
import requests
import time
def solve_geetest(gt, challenge, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "geetest",
"gt": gt,
"challenge": challenge,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"] # Returns dict with three values
raise TimeoutError("GeeTest solve timed out")
Langkah 2: Injeksi ke Playwright (Python)
Ekstrak Parameter
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# Capture GeeTest registration response
geetest_data = {}
def capture_geetest(response):
if "register" in response.url and response.status == 200:
try:
data = response.json()
if "gt" in data and "challenge" in data:
geetest_data.update(data)
except Exception:
pass
page.on("response", capture_geetest)
page.goto("https://staging.example.com/qa-login")
page.wait_for_selector(".geetest_holder")
gt = geetest_data["gt"]
challenge = geetest_data["challenge"]
Injeksi Solusi
# Solve with CaptchaAI
solution = solve_geetest(gt, challenge, page.url)
# Method 1: Set hidden form fields
page.evaluate(f"""
const fields = {{
'geetest_challenge': '{solution["geetest_challenge"]}',
'geetest_validate': '{solution["geetest_validate"]}',
'geetest_seccode': '{solution["geetest_seccode"]}'
}};
for (const [name, value] of Object.entries(fields)) {{
let input = document.querySelector(`input[name="${{name}}"]`);
if (!input) {{
input = document.createElement('input');
input.type = 'hidden';
input.name = name;
document.querySelector('form').appendChild(input);
}}
input.value = value;
}}
""")
# Submit form
page.click("#submit-button")
Metode 2: Trigger JavaScript Callback
Beberapa situs menggunakan JavaScript callback GeeTest alih-alih form field:
page.evaluate(f"""
// Find the GeeTest captcha object
if (window.captchaObj) {{
// Simulate a successful solve
const result = {{
geetest_challenge: '{solution["geetest_challenge"]}',
geetest_validate: '{solution["geetest_validate"]}',
geetest_seccode: '{solution["geetest_seccode"]}'
}};
// Override getValidate to return our solution
window.captchaObj.getValidate = function() {{ return result; }};
// Trigger the success callback
const successEvent = new Event('geetest_success');
document.dispatchEvent(successEvent);
}}
""")
Langkah 3: Injeksi ke Puppeteer (JavaScript)
const puppeteer = require('puppeteer');
async function solveAndInject() {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
// Capture GeeTest params
let gt, challenge;
page.on('response', async (response) => {
if (response.url().includes('register') && response.status() === 200) {
try {
const data = await response.json();
if (data.gt && data.challenge) {
gt = data.gt;
challenge = data.challenge;
}
} catch (e) {}
}
});
await page.goto('https://staging.example.com/qa-login');
await page.waitForSelector('.geetest_holder');
// Solve with CaptchaAI (implementation from earlier)
const solution = await solveCaptcha(gt, challenge, page.url());
// Inject the three values
await page.evaluate((sol) => {
// Set hidden inputs
const form = document.querySelector('form');
['geetest_challenge', 'geetest_validate', 'geetest_seccode'].forEach(name => {
let input = document.querySelector(`input[name="${name}"]`);
if (!input) {
input = document.createElement('input');
input.type = 'hidden';
input.name = name;
form.appendChild(input);
}
input.value = sol[name];
});
}, solution);
await page.click('#submit-button');
}
Langkah 4: Injeksi ke Selenium (Python)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")
# Wait for GeeTest widget
WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.CLASS_NAME, "geetest_holder"))
)
# Extract gt and challenge from the page
gt = driver.execute_script(
"return document.querySelector('[data-gt]')?.dataset.gt"
)
challenge = driver.execute_script(
"return document.querySelector('[data-challenge]')?.dataset.challenge"
)
# Solve with CaptchaAI
solution = solve_geetest(gt, challenge, driver.current_url)
# Inject via JavaScript
driver.execute_script(f"""
var fields = {{
'geetest_challenge': '{solution["geetest_challenge"]}',
'geetest_validate': '{solution["geetest_validate"]}',
'geetest_seccode': '{solution["geetest_seccode"]}'
}};
var form = document.querySelector('form');
for (var name in fields) {{
var input = document.querySelector('input[name="' + name + '"]');
if (!input) {{
input = document.createElement('input');
input.type = 'hidden';
input.name = name;
form.appendChild(input);
}}
input.value = fields[name];
}}
""")
driver.find_element(By.ID, "submit-button").click()
Menangani Submit Berbasis XHR
Beberapa situs mengirimkan hasil GeeTest via XHR, bukan form POST. Intercept dan ubah request:
# Playwright: Intercept the XHR and inject values
def handle_route(route):
if "login" in route.request.url and route.request.method == "POST":
# Modify the POST data to include our solution
post_data = route.request.post_data
# Add GeeTest values to the request
route.continue_(post_data=modified_data)
else:
route.continue_()
page.route("**/api/login**", handle_route)
Pemecahan Masalah
| Masalah | Penyebab | Perbaikan |
|---|---|---|
| "GeeTest validation failed" | Satu dari tiga nilai tidak ada | Verifikasi ketiganya disuntikkan |
| Challenge kedaluwarsa sebelum injeksi | Jeda terlalu lama antara ekstraksi dan solve | Ekstrak dan solve secara berurutan |
| Form submit tapi nilai tidak disertakan | Nama field atau selector form salah | Cek form sesungguhnya untuk nama yang benar |
| Callback tidak terpicu | Situs menggunakan nama callback kustom | Temukan callback di opsi initGeetest |
| Nilai disuntikkan tapi widget masih tampil | State widget tidak diperbarui | Trigger success callback secara programatik |
Pertanyaan Umum
Apakah saya perlu menyembunyikan widget GeeTest secara visual setelah injeksi?
Tidak. State visual widget tidak mempengaruhi submit form. Selama ketiga nilai ada dalam data form, server akan memvalidasinya terlepas dari tampilan widget.
Bisakah saya menyuntikkan nilai GeeTest tanpa browser?
Ya, jika situs menerima HTTP POST langsung dengan ketiga nilai tersebut. Intercept endpoint submit form dan kirimkan via requests atau HTTP client lainnya.
Mengapa GeeTest menggunakan tiga nilai terpisah, bukan satu token?
Ketiga nilai memiliki tujuan berbeda: geetest_challenge melacak sesi, geetest_validate membuktikan challenge telah diselesaikan, dan geetest_seccode menyediakan hash untuk deteksi tampering.
Artikel Terkait
- Solving GeeTest v3 dengan Node.js dan CaptchaAI
- CAPTCHA Solving di Mobile Browser Automation
Langkah Selanjutnya
Menyuntikkan solusi GeeTest dalam kerangka apa pun —dapatkan kunci API CaptchaAI Andadan mulai menyelesaikannya.