API Tutorials

Optimasi Latensi API CaptchaAI: Solve Lebih Cepat

Sebagian besar waktu dalam satu siklus solve CAPTCHA tidak dihabiskan oleh solver-nya, melainkan oleh cara aplikasi Anda menunggu dan mengambil hasil. Kabar baiknya, bagian itulah yang paling bisa Anda kendalikan — terutama jika scraper Anda berjalan jauh dari infrastruktur solver, misalnya di region ap-southeast-3 (Jakarta) atau ap-southeast-1 (Singapura), di mana setiap round-trip jaringan ikut menambah beban. Artikel ini menelusuri tujuh optimasi konkret dengan contoh kode Python dan JavaScript.

Empat sumber latensi dalam satu solve

Sebelum mengoptimasi, pahami dulu ke mana waktu Anda pergi. Satu siklus solve punya empat komponen:

  • Pengiriman task (submit) — request pertama Anda ke in.php.
  • Antrean — jeda sebelum solver mengambil task dari antrean.
  • Eksekusi solver — waktu penyelesaian sebenarnya; komponen ini ada di tangan CaptchaAI.
  • Pengambilan hasil — polling ke res.php sampai token siap.

Anda tidak bisa memangkas eksekusi solver, tetapi tiga komponen lainnya sepenuhnya bisa Anda perbaiki. Di situlah seluruh usaha optimasi sebaiknya diarahkan.

Latensi dasar per jenis CAPTCHA

Tetapkan titik awal sebelum mengubah apa pun. Tabel berikut memisahkan batas SLA resmi CaptchaAI (plafon per jenis) dari angka realistis yang biasa dicapai setelah menerapkan optimasi di bawah:

Jenis CAPTCHA Batas SLA Realistis setelah optimasi
Gambar/OCR <0.5 detik 0.2–0.4 detik
reCAPTCHA v2 <60 detik 10–20 detik
reCAPTCHA v3 <4 detik 1–3 detik
Cloudflare Turnstile <10 detik 4–8 detik
GeeTest v3 <12 detik 6–10 detik

Angka pada kolom kanan bersumber dari pengamatan dan bisa berbeda tergantung lingkungan, volume, dan waktu pengujian. Perlakukan sebagai target, bukan janji.

1. Atur interval polling secara adaptif

Interval polling default 5 detik membuang waktu: jika solve selesai tepat setelah satu poll, Anda baru mengetahuinya lima detik kemudian. Adaptive polling mengatasi ini — mulai agresif di awal, lalu melebar setelah beberapa percobaan agar tidak membanjiri endpoint. Pola berikut memulai di 3 detik dan naik ke 5 detik setelah empat poll:

Python

import time
import requests

API_KEY = "YOUR_API_KEY"
RESULT_URL = "https://ocr.captchaai.com/res.php"

def adaptive_poll(task_id, timeout=120):
    """Start polling at 3s, increase to 5s after 4 polls."""
    start = time.time()
    interval = 3  # start aggressive
    polls = 0

    while time.time() - start < timeout:
        time.sleep(interval)
        polls += 1

        resp = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": "1"
        }).json()

        if resp["status"] == 1:
            elapsed = time.time() - start
            print(f"Solved in {elapsed:.1f}s ({polls} polls)")
            return resp["request"]

        if resp["request"] != "CAPCHA_NOT_READY":
            raise Exception(resp["request"])

        # Back off after initial fast polls
        if polls >= 4:
            interval = 5

    raise TimeoutError(f"Task {task_id} timed out")

JavaScript

async function adaptivePoll(taskId, apiKey, timeout = 120000) {
  const start = Date.now();
  let interval = 3000;
  let polls = 0;

  while (Date.now() - start < timeout) {
    await new Promise(r => setTimeout(r, interval));
    polls++;

    const resp = await fetch(
      `https://ocr.captchaai.com/res.php?key=${apiKey}&action=get&id=${taskId}&json=1`
    );
    const data = await resp.json();

    if (data.status === 1) {
      console.log(`Solved in ${((Date.now() - start) / 1000).toFixed(1)}s (${polls} polls)`);
      return data.request;
    }
    if (data.request !== 'CAPCHA_NOT_READY') {
      throw new Error(data.request);
    }

    if (polls >= 4) interval = 5000;
  }
  throw new Error(`Task ${taskId} timed out`);
}

Dua hal yang perlu diingat saat memakai pola ini:

  • Rata-rata menghemat 1–4 detik dibanding interval tetap 5 detik.
  • Jangan turunkan interval di bawah 3 detik — polling terlalu rapat memicu pembatasan laju permintaan (rate limiting) dan menghapus keuntungannya.

2. Pakai ulang koneksi HTTP (connection pooling)

Setiap poll yang membuka koneksi TCP/TLS baru membayar ulang biaya handshake. Untuk scraper yang melakukan ratusan hingga ribuan poll, biaya ini menumpuk cepat. Pakai ulang satu koneksi alih-alih membuka yang baru:

Python

session = requests.Session()
# Use session.get() and session.post() instead of requests.get/post
# The session reuses TCP connections automatically

JavaScript (Node.js)

const { Agent } = require('http');
const axios = require('axios');

const client = axios.create({
  httpAgent: new Agent({ keepAlive: true, maxSockets: 10 }),
  timeout: 10000,
});
// Use client.get() and client.post() for all API calls

Penghematannya sekitar 50–100 ms per request karena handshake TCP/TLS dilewati. Efeknya paling terasa saat aplikasi Anda berjalan jauh dari infrastruktur solver: pada deployment di Jakarta atau Singapura, penghematan per-request ini terakumulasi menjadi selisih nyata di sepanjang satu job besar.

3. Pre-fetch token CAPTCHA lebih awal

Inilah optimasi dengan dampak terbesar: kirim task CAPTCHA sebelum tokennya benar-benar dibutuhkan. Saat scraper memproses halaman N, submit CAPTCHA untuk halaman N+1 secara paralel, sehingga solve berjalan bersamaan dengan pemrosesan Anda:

from concurrent.futures import ThreadPoolExecutor

SUBMIT_URL = "https://ocr.captchaai.com/in.php"

def prefetch_submit(sitekey, page_url):
    resp = session.post(SUBMIT_URL, data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": page_url,
        "json": "1",
    })
    data = resp.json()
    if data["status"] == 1:
        return data["request"]
    raise Exception(data["request"])

# Submit next page's CAPTCHA while processing current page
with ThreadPoolExecutor(max_workers=2) as pool:
    # Submit CAPTCHA for page 2 while processing page 1
    future_task = pool.submit(prefetch_submit, "6Le-SITEKEY", "https://example.com/page/2")

    # Process page 1...
    process_page(current_data)

    # Now get the pre-submitted task ID and poll
    task_id = future_task.result()
    token = adaptive_poll(task_id)

Karena solve berjalan paralel dengan pemrosesan, waktu tunggu praktis hilang — untuk alur sekuensial, latensi yang dirasakan bisa mendekati nol. Dua catatan penting soal biaya dan kapasitas:

  • CaptchaAI menagih per thread, bukan per solve, jadi pre-fetch tidak menambah biaya per CAPTCHA.
  • Anda hanya perlu thread yang cukup untuk menampung solve paralel. Paket ADVANCE ($90/bulan, 50 thread, solve tak terbatas) memberi ruang paralel yang lega untuk pola seperti ini.

4. Pilih metode CAPTCHA yang paling efisien

CaptchaAI kadang menyediakan metode yang lebih ringan untuk skenario tertentu. Memilih metode yang tepat sejak awal menghindari kerja solver yang tidak perlu:

Skenario Metode standar Alternatif lebih ringan
reCAPTCHA v2 dengan callback diketahui userrecaptcha + polling userrecaptcha dengan pingback (callback URL)
CAPTCHA teks pada gambar base64 resolusi tinggi base64 dengan numeric=1 bila hanya angka

5. Aktifkan proxy hanya saat benar-benar perlu

Routing lewat proxy selalu menambah hop jaringan, sehingga menambah latensi. Kirim parameter proxy hanya ketika situs target memang mengharuskan request datang dari IP tertentu; untuk mayoritas kasus, tanpa proxy lebih ringan:

# Without proxy — faster for most use cases
data = {
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "json": "1",
}

# With proxy — only when required
data["proxy"] = "user:pass@1.2.3.4:8080"
data["proxytype"] = "HTTP"

Kasus yang benar-benar menuntut proxy relatif sedikit:

  • Situs target membatasi akses ke rentang IP tertentu (geo-fencing atau allowlist).
  • Anda butuh konsistensi IP antar-request dalam satu sesi terautentikasi milik sendiri.

Di luar itu, biarkan parameter proxy kosong dan nikmati jalur yang lebih pendek.

6. Ganti polling dengan callback URL

Anda bisa menghapus loop polling sepenuhnya lewat parameter pingback:

resp = session.post(SUBMIT_URL, data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "json": "1",
    "pingback": "https://your-server.com/captcha-callback",
})

Begitu solve selesai, CaptchaAI mengirim hasil langsung ke URL Anda. Keunggulannya:

  • Tidak ada satu pun poll yang perlu dijalankan, sehingga tidak ada jeda polling sama sekali — inilah cara pengambilan hasil dengan overhead paling kecil.
  • Cocok untuk arsitektur event-driven, dengan syarat server Anda punya endpoint publik yang bisa dijangkau CaptchaAI.

7. Ukur hasil optimasi dengan benchmark

Jangan menebak — ukur. Jalankan tiap perubahan terhadap beban yang realistis, lalu bandingkan median dan P95, bukan sekadar rata-rata, karena ekor latensi (P95) yang paling terasa di produksi:

import statistics

def benchmark(solve_func, iterations=20):
    times = []
    for i in range(iterations):
        start = time.time()
        try:
            solve_func()
            times.append(time.time() - start)
        except Exception:
            pass

    if times:
        print(f"Samples: {len(times)}/{iterations}")
        print(f"Mean:    {statistics.mean(times):.1f}s")
        print(f"Median:  {statistics.median(times):.1f}s")
        print(f"P95:     {sorted(times)[int(len(times)*0.95)]:.1f}s")
        print(f"Min:     {min(times):.1f}s")
        print(f"Max:     {max(times):.1f}s")

Pemecahan masalah umum

Masalah Penyebab Solusi
Latensi polling tidak berubah Masih memakai requests.get() tanpa session Ganti ke session.get()
Token pre-fetch kedaluwarsa sebelum dipakai Pemrosesan terlalu lama Persempit jendela pre-fetch atau submit lebih dekat ke waktu pakai
Callback URL tidak pernah menerima data Server tidak terjangkau dari CaptchaAI Pastikan URL publik dan aturan firewall benar
Polling terlalu rapat memicu rate limiting Interval di bawah 2 detik Jaga interval minimum 3 detik

Pertanyaan yang sering muncul

Apakah menambah jumlah thread membuat solve satu CAPTCHA lebih cepat?

Tidak. Thread menentukan berapa banyak CAPTCHA yang bisa diselesaikan secara bersamaan (konkuren), bukan seberapa cepat satu CAPTCHA selesai. Menambah thread menaikkan throughput total — berguna untuk pre-fetch dan paralelisasi — tetapi latensi per solve tetap ditentukan oleh jenis CAPTCHA dan optimasi jaringan di artikel ini.

Berapa interval polling minimum yang aman?

Pertahankan minimal 3 detik. Interval di bawah 2 detik cenderung memicu pembatasan laju permintaan (rate limiting) tanpa mempercepat hasil, karena solve belum tentu selesai secepat itu. Adaptive polling di bagian 1 sudah menyeimbangkan kecepatan awal dengan keamanan interval.

Kapan callback URL lebih baik daripada polling?

Pakai callback URL saat Anda punya server dengan endpoint publik dan ingin menghapus seluruh overhead polling — ideal untuk arsitektur event-driven. Tetap gunakan polling saat berjalan dari lingkungan tanpa endpoint publik, seperti skrip lokal atau job batch di balik NAT.

Apakah adaptive polling berpengaruh untuk CAPTCHA gambar?

Hampir tidak. CAPTCHA gambar selesai di bawah 0.5 detik, sehingga poll pertama pada 3 detik biasanya sudah langsung mendapat hasil. Manfaat adaptive polling jauh lebih terasa pada reCAPTCHA yang butuh puluhan detik.

Pangkas latensi solve CAPTCHA Anda

Ambil API key CaptchaAI dan mulai uji latensi solve pertama Anda di captchaai.com.

Panduan terkait

Komentar dinonaktifkan untuk artikel ini.