API Tutorials

CaptchaAI API Latency Optimization: Faster Solves

A CAPTCHA solve has four latency components: submit request, queue wait, solver execution, and poll retrieval. You can't control solver execution time, but you can optimize everything else.


Baseline latency by CAPTCHA type

CAPTCHA type Typical solve time Best achievable
Image/OCR 2-5s 1-3s
reCAPTCHA v2 15-30s 10-20s
reCAPTCHA v3 10-20s 8-15s
Cloudflare Turnstile 10-25s 8-15s
GeeTest v3 15-30s 10-20s

The "best achievable" column reflects what you get after applying the optimizations below.


1. Optimize poll intervals

The default 5-second poll interval wastes time when the solve completes between polls. Use adaptive polling — start fast, then back off:

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`);
}

Saves 1-4 seconds on average compared to a fixed 5-second interval.


2. Connection pooling

Reuse HTTP connections instead of opening new ones for each poll:

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

Saves ~50-100ms per request by skipping TCP/TLS handshakes.


3. Prefetch CAPTCHAs

Submit CAPTCHA tasks before you need the tokens. While your scraper processes page N, submit the CAPTCHA for page N+1:

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)

Eliminates the full wait time by overlapping solving with processing.


4. Use the right CAPTCHA method

CaptchaAI sometimes supports faster methods for specific scenarios:

Scenario Slow method Faster alternative
reCAPTCHA v2 with known callback userrecaptcha + poll userrecaptcha with pingback (callback URL)
Image text CAPTCHA base64 with high resolution base64 with numeric=1 if digits only
reCAPTCHA v3 Default min_score Set min_score to the actual threshold needed (lower = faster)

5. Skip the proxy when not needed

Proxy routing adds latency. Only send proxy parameters when the target site requires requests from specific IPs:

# 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"

6. Use callback URLs instead of polling

Eliminate polling entirely with the pingback parameter:

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",
})

CaptchaAI sends the result to your URL when the solve completes. No polling loop needed. This is the fastest retrieval method.


7. Benchmark your optimizations

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")

Troubleshooting

Problem Cause Fix
Poll latency unchanged Still using requests.get() without session Switch to session.get()
Prefetch tokens expire before use Processing takes too long Reduce prefetch window or submit closer to usage
Callback URL never receives data Server not reachable from CaptchaAI Ensure public URL, correct firewall rules
Faster polling causes rate limits Polling too aggressively (< 2s) Keep minimum interval at 3 seconds

FAQ

What's the biggest single optimization?

Prefetching. It overlaps solve time with processing time, effectively reducing perceived latency to near zero for sequential workflows.

Does adaptive polling help for image CAPTCHAs?

Less so. Image CAPTCHAs solve in 2-5 seconds, so the first poll at 3 seconds often catches them. The improvement is more noticeable for reCAPTCHA (15-30 seconds).


Get the fastest CAPTCHA solving with CaptchaAI

Get your API key at captchaai.com.


Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.