API Tutorials

Parameter GeeTest Slide CAPTCHA dan Panduan API

Request GeeTest v3 Anda ke CaptchaAI ditolak dengan ERROR_CAPTCHA_UNSOLVABLE, padahal kode terlihat sudah benar? Penyebabnya hampir selalu satu dari empat parameter berikut: gt yang salah salin, challenge yang sudah basi saat sampai ke server, pageurl yang tidak persis sama dengan URL halaman asli, atau api_server yang terlewat ketika situs memakai subdomain GeeTest kustom. Panduan ini membedah keempat parameter itu satu per satu — cara mengekstraknya dari halaman target, cara mengirimkannya ke CaptchaAI, dan cara memakai hasil solve untuk validasi — lengkap dengan contoh Python yang bisa langsung Anda jalankan.

Alur ini umum dipakai tim QA dan scraping di Indonesia yang memantau harga di situs e-commerce atau menguji flow checkout yang dilindungi GeeTest slide CAPTCHA. Kalau skrip Anda berjalan dari server di region ap-southeast-1 (Singapura) atau asia-southeast2 (Jakarta), latensi jaringan ke halaman target maupun ke API CaptchaAI ikut memengaruhi seberapa cepat challenge harus dikirim sebelum basi — jadi timeout dan interval polling di bawah bukan angka sembarangan.


Empat Parameter yang Wajib Ada di Setiap Request GeeTest v3

CaptchaAI menerima empat field untuk method geetest. Dua di antaranya nyaris statis per situs, dua lainnya berubah setiap sesi — inilah yang membedakan integrasi GeeTest dari reCAPTCHA atau Turnstile:

Parameter Wajib Keterangan
gt Ya ID akun GeeTest milik situs (hex 32 karakter). Ada di source halaman atau respons API register
challenge Ya String challenge unik per sesi. Harus diambil ulang untuk setiap solve baru
pageurl Ya URL lengkap halaman yang menampilkan widget GeeTest
api_server Tidak Subdomain server API GeeTest kustom, hanya diisi jika situs tidak pakai default

gt biasanya tidak berubah selama situs tidak mengganti konfigurasi akun GeeTest-nya, jadi Anda bisa menyimpannya sekali dan memakainya berulang kali. challenge sebaliknya — ia wajib fresh setiap kali, dan bagian berikut menunjukkan cara mengambil keduanya langsung dari halaman.


Cara Mengambil gt dan challenge dari Halaman Target

Ada dua sumber untuk kedua parameter ini: HTML halaman itu sendiri, atau endpoint register-slide yang dipanggil browser saat widget GeeTest dimuat. Fungsi berikut mencoba HTML dulu, lalu jatuh ke panggilan API kalau gt atau challenge tidak ditemukan di markup:

# extract_geetest_params.py
import requests
import re
import json


def extract_geetest_v3(page_url, session=None):
    """Extract GeeTest v3 gt and challenge from a page."""
    if session is None:
        session = requests.Session()
        session.headers["User-Agent"] = (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36"
        )

    resp = session.get(page_url, timeout=15)
    html = resp.text

    # Method 1: Extract gt from HTML
    gt_match = re.search(r'gt["\']?\s*[:=]\s*["\']([a-f0-9]{32})', html)
    gt = gt_match.group(1) if gt_match else None

    # Method 2: Find API endpoint that returns challenge
    api_match = re.search(r'(https?://[^"\']+register-slide[^"\']*)', html)

    challenge = None
    if api_match:
        api_url = api_match.group(1)
        api_resp = session.get(api_url, timeout=10)
        try:
            data = api_resp.json()
            challenge = data.get("challenge")
            gt = gt or data.get("gt")
        except json.JSONDecodeError:
            pass

    if not challenge:
        # Try embedded challenge
        ch_match = re.search(r'challenge["\']?\s*[:=]\s*["\']([a-f0-9]+)', html)
        challenge = ch_match.group(1) if ch_match else None

    return {"gt": gt, "challenge": challenge, "pageurl": page_url}


# Usage
params = extract_geetest_v3("https://staging.example.com/qa-login")
print(f"gt: {params['gt']}")
print(f"challenge: {params['challenge']}")

Kalau gt maupun challenge tetap None setelah fungsi ini jalan, kemungkinan besar keduanya dimuat sepenuhnya lewat JavaScript — bagian troubleshooting di bawah membahas solusinya dengan Selenium atau Playwright. Untuk situs yang me-render server-side, pola regex di atas biasanya sudah cukup.


Mengirim Parameter ke API CaptchaAI

Setelah gt, challenge, dan pageurl di tangan, kirimkan sebagai payload method: "geetest" ke endpoint in.php. CaptchaAI membalas dengan task_id, lalu Anda polling res.php sampai statusnya berubah jadi selesai. GeeTest v3 biasanya clear dalam waktu kurang dari 12 detik dengan tingkat keberhasilan tinggi pada tipe yang didukung, tapi kode di bawah tetap menunggu jeda awal sebelum polling pertama supaya tidak membombardir endpoint dengan request kosong:

# solve_geetest.py
import requests
import time
import os


def solve_geetest(gt, challenge, pageurl, api_server=None):
    """Solve GeeTest v3 slide CAPTCHA via CaptchaAI."""
    api_key = os.environ["CAPTCHAAI_API_KEY"]

    payload = {
        "key": api_key,
        "method": "geetest",
        "gt": gt,
        "challenge": challenge,
        "pageurl": pageurl,
        "json": 1,
    }

    if api_server:
        payload["api_server"] = api_server

    # Submit
    resp = requests.post(
        "https://ocr.captchaai.com/in.php",
        data=payload,
        timeout=30,
    )
    result = resp.json()

    if result.get("status") != 1:
        raise RuntimeError(f"Submit failed: {result.get('request')}")

    task_id = result["request"]

    # Poll — GeeTest typically solves in 10-20 seconds
    time.sleep(10)
    for _ in range(30):
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key,
            "action": "get",
            "id": task_id,
            "json": 1,
        }, timeout=15)
        data = resp.json()

        if data.get("status") == 1:
            return data["request"]  # Returns challenge, validate, seccode
        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(5)

    raise TimeoutError("GeeTest solve timeout")

Perhatikan time.sleep(10) sebelum loop polling dimulai — itu bukan angka acak, melainkan jeda awal yang mengikuti kecepatan solve rata-rata GeeTest sebelum Anda mulai mengecek status. Kalau tim Anda memakai callback alih-alih polling, field pingback bisa ditambahkan ke payload di atas supaya CaptchaAI mengirim hasil begitu selesai, tanpa Anda perlu loop sama sekali.


Memakai Hasil Solve untuk Validasi di Situs Target

Hasil solve GeeTest berisi tiga field yang harus Anda teruskan ke endpoint validasi situs target — bukan endpoint CaptchaAI: geetest_challenge, geetest_validate, dan geetest_seccode. Tanpa ketiganya lengkap, situs akan menolak solusi meskipun CaptchaAI sudah menandainya berhasil:

# submit_solution.py
import json


def submit_geetest_solution(session, validation_url, solution, original_challenge):
    """Submit GeeTest solution to the target site."""
    # Parse solution if string
    if isinstance(solution, str):
        solution = json.loads(solution)

    payload = {
        "geetest_challenge": solution.get("challenge", original_challenge),
        "geetest_validate": solution.get("validate", ""),
        "geetest_seccode": solution.get("seccode", ""),
    }

    resp = session.post(validation_url, data=payload, timeout=30)
    return resp


# Complete flow
def full_geetest_flow(page_url, validation_url):
    import requests
    from extract_geetest_params import extract_geetest_v3

    session = requests.Session()
    session.headers["User-Agent"] = (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36"
    )

    # Step 1: Extract parameters
    params = extract_geetest_v3(page_url, session)
    print(f"gt: {params['gt']}, challenge: {params['challenge'][:16]}...")

    # Step 2: Solve
    solution = solve_geetest(
        params["gt"], params["challenge"], params["pageurl"],
    )
    print("Solved!")

    # Step 3: Submit
    resp = submit_geetest_solution(
        session, validation_url, solution, params["challenge"],
    )
    print(f"Validation response: {resp.status_code}")
    return resp

Fungsi full_geetest_flow di atas merangkum tiga langkah sekaligus — ekstrak, solve, kirim — jadi Anda tinggal memanggilnya dengan URL halaman dan URL endpoint validasi situs target.


Kenapa challenge Cepat Basi — dan Cara Menyiasatinya

challenge biasanya hanya valid 60–120 detik sejak diterbitkan situs. Kalau ada jeda antara ekstraksi dan pengiriman ke CaptchaAI — misalnya karena antrean job scraping atau proxy yang lambat — challenge sudah kedaluwarsa duluan sebelum sempat disolve. Pola amannya: ambil challenge sesaat sebelum solve, bukan di awal skrip:

# fresh_challenge.py
import time


def get_fresh_challenge(session, register_url):
    """Always fetch a fresh challenge before solving."""
    resp = session.get(register_url, timeout=10)
    data = resp.json()

    challenge = data.get("challenge")
    if not challenge:
        raise ValueError("No challenge returned")

    return challenge


def solve_with_fresh_challenge(session, gt, register_url, pageurl):
    """Ensure challenge is fresh before submitting to CaptchaAI."""
    challenge = get_fresh_challenge(session, register_url)

    # Submit immediately — don't let it expire
    solution = solve_geetest(gt, challenge, pageurl)
    return solution

Aturan utama: ambil challenge dan kirim ke CaptchaAI dalam hitungan detik, bukan menit. Challenge yang sudah basi akan selalu gagal, berapa pun kuat retry logic Anda.


Kapan Anda Perlu api_server Kustom

Sebagian besar situs memakai server default GeeTest, jadi api_server boleh dikosongkan. Tapi beberapa situs — terutama yang melayani traffic regional tertentu — mengarahkan widget-nya ke subdomain lain seperti api-na.geetest.com. Kalau parameter ini tidak diisi padahal situsnya butuh, solve akan gagal walau gt dan challenge sudah benar:

# The api_server parameter specifies a custom GeeTest backend
# Default: api.geetest.com
# Custom examples: api-na.geetest.com, api.geetest.com/ajax-custom

solution = solve_geetest(
    gt="abc123...",
    challenge="def456...",
    pageurl="https://staging.example.com/qa-login",
    api_server="api-na.geetest.com",  # North America endpoint
)

Cara mengeceknya: buka DevTools, filter request ke domain yang mengandung geetest.com, lalu lihat host yang benar-benar dipanggil browser. Salin persis apa adanya ke parameter api_server.


Troubleshooting: Error GeeTest v3 yang Paling Sering Muncul

Empat masalah ini menutupi hampir semua kasus gagal solve GeeTest v3 yang dilaporkan tim QA:

Masalah Penyebab Perbaikan
ERROR_CAPTCHA_UNSOLVABLE Challenge sudah basi saat submit Ambil challenge baru tepat sebelum mengirim, jangan di awal skrip
validate kosong pada respons Situs sudah migrasi ke GeeTest v4 GeeTest v4 belum didukung CaptchaAI (status: segera hadir) — pastikan target masih memakai v3
Solusi ditolak situs Field seccode tidak ikut dikirim Pastikan ketiga field (geetest_challenge, geetest_validate, geetest_seccode) lengkap
Parameter gt tidak ditemukan Dimuat lewat JavaScript penuh Pakai Selenium/Playwright, atau tangkap respons XHR ke endpoint register

Kalau keempat perbaikan di atas sudah dicoba dan solve tetap gagal, log task_id beserta payload yang dikirim — biasanya penyebabnya bukan di kode Anda, melainkan pageurl yang tidak persis sama dengan URL yang dilihat browser (misalnya kurang parameter query atau beda protokol http/https).


Pertanyaan yang Sering Diajukan

Apa bedanya gt dan challenge?

gt adalah ID akun GeeTest milik situs — nilainya tetap sepanjang situs tidak berganti konfigurasi. challenge dibuat ulang setiap sesi dan wajib diekstrak fresh setiap kali Anda mau solve.

Berapa lama challenge valid sebelum harus diambil ulang?

Umumnya 60–120 detik. Begitu Anda mendapat nilainya, langsung kirim ke CaptchaAI — jangan disimpan dulu untuk dipakai nanti.

Apakah GeeTest v4 sudah didukung CaptchaAI?

Belum. GeeTest v4 berstatus segera hadir dan belum bisa disolve lewat CaptchaAI. Panduan ini khusus untuk GeeTest v3 — kalau situs target sudah memakai widget v4, parameter dan endpoint di atas tidak akan cocok.

Kenapa CaptchaAI membalas ERROR_CAPTCHA_UNSOLVABLE padahal parameter sudah benar?

Penyebab paling umum adalah challenge yang sudah basi — nilainya kedaluwarsa antara saat diekstrak dan saat sampai ke server CaptchaAI. Perkecil jeda itu, atau ambil challenge baru tepat sebelum memanggil solve_geetest().

Berapa biaya solve GeeTest v3 lewat CaptchaAI?

CaptchaAI memakai skema thread, bukan per-solve — plan BASIC ($15/bulan, 5 thread) sudah mencakup solve tanpa batas selama thread tersedia. Untuk volume scraping harian yang lebih besar, tim QA umumnya naik ke STANDARD ($30/bulan, 15 thread) atau ADVANCE ($90/bulan, 50 thread). Cek harga terbaru di halaman pricing CaptchaAI sebelum memilih plan.


Baca Juga


Kuasai parameter GeeTest v3 dari hulu ke hilir — mulai integrasi dengan CaptchaAI.

Komentar dinonaktifkan untuk artikel ini.