Patokannya sederhana: di bawah 500 penyelesaian per hari, sekuensial sudah cukup dan jauh lebih mudah dirawat; di atas angka itu, paralel adalah cara realistis mengejar throughput tanpa menunggu satu tugas selesai sebelum memulai berikutnya. Memori, penanganan error, dan biaya hanyalah konsekuensi yang mengikuti keputusan volume tadi. Artikel ini membandingkan kedua pendekatan di CaptchaAI, lengkap dengan angka throughput dan contoh kode siap pakai.
Kapan sekuensial, kapan paralel
Keputusan pertama bukan soal kode, melainkan volume harian Anda.
- Di bawah ~500 penyelesaian/hari — tetap sekuensial: alur lurus, mudah di-debug, memori minim.
- Di atas ~500/hari — beralih ke paralel. Pada median 15 detik per reCAPTCHA v2, jalur sekuensial mentok di ~240 penyelesaian per jam dan antrean akan menumpuk lebih cepat daripada terselesaikan.
Contoh nyata: agensi price-monitoring di Jakarta yang memantau ribuan halaman produk tiap pagi mudah menembus 2.000–3.000 penyelesaian/hari. Secara sekuensial pada 15 detik per tugas, itu berjam-jam non-stop; dengan 50 penyelesaian paralel, beban yang sama rampung dalam hitungan menit. Karena CaptchaAI menagih per thread (bukan per permintaan bersamaan), menaikkan konkurensi tidak menambah biaya — Anda hanya mencapai total lebih cepat. Untuk latensi terendah, deploy worker di region terdekat: AWS ap-southeast-1 (Singapura) atau ap-southeast-3 (Jakarta).
Perbandingan singkat: sekuensial vs paralel
| Faktor | Sekuensial | Paralel |
|---|---|---|
| Throughput (reCAPTCHA v2, median 15 detik) | ~240/jam | ~10.000+/jam |
| Kompleksitas kode | Sederhana | Sedang hingga kompleks |
| Penanganan error | Langsung | Perlu isolasi error antar-tugas |
| Penggunaan memori | Minimal (~30 MB) | Menyesuaikan konkurensi (~100–500 MB) |
| Biaya API per penyelesaian | Sama | Sama |
| Kesulitan debugging | Mudah | Lebih sulit (race condition, timing) |
| Urutan hasil | Terjaga | Perlu pelacakan eksplisit |
| Paling cocok untuk | < 500 penyelesaian/hari | > 500 penyelesaian/hari |
Throughput per tingkat konkurensi
Setelah tahu Anda butuh paralel, pertanyaan berikutnya adalah berapa thread yang sepadan dengan target volume. Tabel ini memetakan konkurensi ke throughput per jam: naikkan mendekati batas thread paket Anda, lalu berhenti — di atas itu efisiensinya menurun.
Angka berikut bersumber dari pengamatan dan laporan pengguna. Hasil dapat berbeda tergantung lingkungan, volume, dan waktu pengujian.
| Penyelesaian bersamaan | Perkiraan throughput/jam | Memori (Python) | Kompleksitas |
|---|---|---|---|
| 1 (sekuensial) | 240 | 30 MB | Rendah |
| 10 | 2.400 | 50 MB | Rendah |
| 25 | 6.000 | 80MB | Sedang |
| 50 | 10.000+ | 120 MB | Sedang |
| 100 | 18.000+ | 200 MB | Tinggi |
Berdasarkan reCAPTCHA v2 dengan waktu penyelesaian median 15 detik.
Penyelesaian sekuensial
Model paling sederhana: satu CAPTCHA dalam satu waktu — kirim, tunggu, polling, ambil hasil, lalu lanjut ke tugas berikutnya. Jalur eksekusinya lurus, jadi paling mudah dibaca dan di-debug saat ada yang meleset.
# sequential_solver.py
import os
import time
import requests
API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
def solve_sequential(tasks):
"""Solve CAPTCHAs one by one."""
results = []
session = requests.Session()
for task in tasks:
# Submit
resp = session.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": task["sitekey"],
"pageurl": task["pageurl"],
"json": "1",
})
result = resp.json()
if result.get("status") != 1:
results.append({"error": result.get("request")})
continue
task_id = result["request"]
time.sleep(15)
# Poll
token = None
for _ in range(25):
poll = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1",
})
poll_result = poll.json()
if poll_result.get("status") == 1:
token = poll_result["request"]
break
if poll_result.get("request") != "CAPCHA_NOT_READY":
break
time.sleep(5)
results.append({"token": token} if token else {"error": "timeout"})
return results
# 10 tasks sequentially → ~150 seconds total
tasks = [{"sitekey": "SITEKEY", "pageurl": "https://example.com"}] * 10
start = time.time()
results = solve_sequential(tasks)
print(f"Completed in {time.time() - start:.0f}s")
Pendekatan ini tetap ideal selama beban ringan dan salah satu kondisi berikut terpenuhi — alur satu halaman saat mengisi satu formulir dalam satu waktu; fase debugging dan pengembangan yang butuh jalur eksekusi jelas; atau tugas bergantung urutan, saat hasil satu penyelesaian dipakai sebelum tugas berikutnya jalan.
Penyelesaian paralel
Balik logikanya: kirim banyak CAPTCHA sekaligus, lalu polling semua hasilnya secara bersamaan. Sebuah semaphore membatasi berapa penyelesaian yang berjalan serentak agar tidak melebihi alokasi thread.
# parallel_solver.py
import os
import asyncio
import aiohttp
API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
async def solve_one(session, sitekey, pageurl, semaphore):
"""Solve a single CAPTCHA within concurrency limits."""
async with semaphore:
# Submit
async with session.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": pageurl, "json": "1",
}) as resp:
result = await resp.json(content_type=None)
if result.get("status") != 1:
return {"error": result.get("request")}
task_id = result["request"]
await asyncio.sleep(15)
# Poll
for _ in range(25):
async with session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1",
}) as resp:
poll_result = await resp.json(content_type=None)
if poll_result.get("status") == 1:
return {"token": poll_result["request"]}
if poll_result.get("request") != "CAPCHA_NOT_READY":
return {"error": poll_result.get("request")}
await asyncio.sleep(5)
return {"error": "timeout"}
async def solve_parallel(tasks, max_concurrent=50):
"""Solve CAPTCHAs in parallel with concurrency control."""
semaphore = asyncio.Semaphore(max_concurrent)
connector = aiohttp.TCPConnector(limit=max_concurrent)
async with aiohttp.ClientSession(connector=connector) as session:
coros = [
solve_one(session, t["sitekey"], t["pageurl"], semaphore)
for t in tasks
]
return await asyncio.gather(*coros)
# 10 tasks in parallel → ~20 seconds total
import time
tasks = [{"sitekey": "SITEKEY", "pageurl": "https://example.com"}] * 10
start = time.time()
results = asyncio.run(solve_parallel(tasks))
print(f"Completed in {time.time() - start:.0f}s")
Jangan setel max_concurrent melebihi jumlah thread di paket Anda. Satu thread adalah satu CAPTCHA yang sedang berjalan, jadi paket ADVANCE ($90/bulan, 50 thread) menjalankan hingga 50 penyelesaian sekaligus; konkurensi di atas alokasi thread hanya membuat sebagian permintaan menunggu.
// parallel_solver.js
const axios = require('axios');
const https = require('https');
const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
const agent = new https.Agent({ keepAlive: true, maxSockets: 50 });
const api = axios.create({ baseURL: 'https://ocr.captchaai.com', httpsAgent: agent });
async function solveOne(sitekey, pageurl) {
const submit = await api.get('/in.php', {
params: { key: API_KEY, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: '1' },
});
if (submit.data.status !== 1) return { error: submit.data.request };
await new Promise(r => setTimeout(r, 15000));
for (let i = 0; i < 25; i++) {
const poll = await api.get('/res.php', {
params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
});
if (poll.data.status === 1) return { token: poll.data.request };
if (poll.data.request !== 'CAPCHA_NOT_READY') return { error: poll.data.request };
await new Promise(r => setTimeout(r, 5000));
}
return { error: 'timeout' };
}
(async () => {
const tasks = Array.from({ length: 10 }, () => ({
sitekey: 'SITEKEY', pageurl: 'https://example.com',
}));
const start = Date.now();
const results = await Promise.all(tasks.map(t => solveOne(t.sitekey, t.pageurl)));
console.log(`Completed in ${((Date.now() - start) / 1000).toFixed(0)}s`);
console.log(`Solved: ${results.filter(r => r.token).length}/${tasks.length}`);
agent.destroy();
})();
Kunci versi Node.js ada di satu agent keepAlive yang dipakai bersama semua permintaan, sehingga koneksi TCP di-reuse alih-alih dibuat ulang tiap solve — perbedaan besar begitu konkurensi naik.
Pendekatan hibrid
Sering kali jawabannya bukan salah satu, melainkan keduanya: jalankan alur kerja secara sekuensial, tetapi kelompokkan penyelesaian CAPTCHA-nya menjadi satu batch paralel.
# Process 10 URLs sequentially, but solve their CAPTCHAs in a parallel batch
urls = get_next_batch() # 10 URLs
captcha_params = [extract_sitekey(url) for url in urls] # Sequential extraction
tokens = asyncio.run(solve_parallel(captcha_params, max_concurrent=10)) # Parallel solving
for url, result in zip(urls, tokens):
submit_form(url, result.get("token")) # Sequential submission
Pola ini menjaga logika bisnis tetap sederhana dan berurutan, sementara bagian paling lambat — menunggu token dari server — dijalankan bersamaan.
Pertanyaan umum
Kenapa versi paralel saya justru lebih lambat dari sekuensial?
Biasanya max_concurrent disetel terlalu rendah, sehingga tugas tetap mengantre. Naikkan hingga mendekati jumlah thread di paket Anda, dan pakai satu koneksi yang di-reuse, bukan koneksi baru per permintaan.
Apa arti ERROR_NO_SLOT_AVAILABLE saat menjalankan solve paralel?
Anda mengirim lebih banyak penyelesaian bersamaan daripada slot thread yang tersedia. Beri jeda kecil antar pengiriman atau turunkan max_concurrent hingga sesuai alokasi thread paket Anda.
Apakah paralel lebih mahal daripada sekuensial?
Tidak. CaptchaAI menagih per thread dengan penyelesaian tanpa batas per thread, bukan per permintaan bersamaan. Biaya API paralel sama persis dengan sekuensial — Anda hanya lebih cepat mencapai total.
Apakah urutan hasil tetap terjaga saat memakai paralel?
Ya, asyncio.gather (Python) dan Promise.all (JavaScript) mengembalikan hasil sesuai urutan input, apa pun urutan selesainya. Untuk pola lain seperti as_completed, lacak indeks tugas secara eksplisit.
Berapa tingkat konkurensi yang masih masuk akal?
Sebagian besar pengaturan mulai kehilangan efisiensi di atas 100 penyelesaian bersamaan, dan konkurensi tetap dibatasi jumlah thread di paket. Setelahnya, optimalkan parameter penyelesaian, bukan konkurensi.
Langkah berikutnya
Pilih strategi yang sesuai dengan volume harian Anda — dapatkan kunci API CaptchaAI.
Panduan terkait: