Tutorials

Capacidade de resolução de CAPTCHA: como processar 10.000 tarefas por hora

Quer processar 10.000 CAPTCHAs por hora? Você não precisa de um solve mais rápido — precisa manter cerca de 42 resoluções em andamento ao mesmo tempo, o tempo todo. É essa simultaneidade (o throughput, ou taxa de transferência) que fecha a conta, não a velocidade de cada requisição isolada. Este guia mostra a matemática por trás desse número, o pipeline assíncrono em Python e Node.js que sustenta esse ritmo com a API da CaptchaAI e qual plano de threads escolher para não virar gargalo.

A matemática por trás de 10 mil resoluções por hora

Parta do tempo de resolução: se uma resolução de reCAPTCHA v2 leva 15 segundos (mediana):

  • Sequencial: 3.600 s / 15 s = 240 soluções/hora
  • Para chegar a 10.000/hora: você precisa de ~42 resoluções simultâneas em andamento o tempo todo

O ponto central: você não está esperando o CaptchaAI ficar mais rápido — você está sobrepondo requisições suficientes para que 42 soluções terminem dentro da mesma janela de 15 segundos.

Quantas threads (e qual plano) isso exige

Cada thread do seu plano CaptchaAI processa uma resolução por vez e fica livre assim que ela termina — não há limite de soluções por thread, só de quantas rodam ao mesmo tempo.

Cenário Plano Threads Preço/mês
Baseline (~42 simultâneas, 15 s/solve) ADVANCE 50 US$ 90
Picos de tráfego ou tipos mais lentos CORPORATE 150 US$ 240

Se o seu tempo médio de resolução for maior que 15 segundos — reCAPTCHA v2 Enterprise, proxies mais lentos, horários de pico —, prefira a linha CORPORATE: ela dá margem sem exigir ajuste fino no pipeline.

Arquitetura do pipeline

┌──────────┐     ┌────────────┐     ┌─────────────┐     ┌──────────┐
│  Task     │────▶│  Submit    │────▶│  CaptchaAI  │────▶│  Result  │
│  Queue    │     │  Workers   │     │  API        │     │  Store   │
│  (Redis)  │     │  (async)   │     │             │     │  (DB)    │
└──────────┘     └────────────┘     └─────────────┘     └──────────┘
                       │                    ▲
                       │    ┌──────────┐    │
                       └───▶│  Poll    │────┘
                            │  Workers │
                            └──────────┘
Componente Função
Fila de tarefas mantém as tarefas CAPTCHA pendentes, com sitekey e URL de cada uma
Workers de envio enviam as tarefas à API da CaptchaAI em paralelo
Workers de consulta verificam o resultado em intervalos otimizados (polling)
Armazenamento de resultados grava os tokens assim que chegam

Python: pipeline assíncrono com aiohttp

O exemplo abaixo usa asyncio e aiohttp, com um semáforo limitando a até 50 resoluções simultâneas em voo:

# high_throughput_solver.py
import os
import asyncio
import time
import aiohttp

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"
MAX_CONCURRENT = 50  # Max simultaneous solves
POLL_INTERVAL = 5    # Seconds between polls
INITIAL_WAIT = 12    # Seconds before first poll

semaphore = asyncio.Semaphore(MAX_CONCURRENT)
stats = {"submitted": 0, "solved": 0, "failed": 0, "start": 0}

async def solve_one(session, sitekey, pageurl, task_num):
    """Submit and poll a single CAPTCHA."""
    async with semaphore:
        try:
            # Submit
            async with session.get(f"{BASE_URL}/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:
                stats["failed"] += 1
                return None

            stats["submitted"] += 1
            task_id = result["request"]

            # Wait before first poll
            await asyncio.sleep(INITIAL_WAIT)

            # Poll
            for _ in range(25):
                async with session.get(f"{BASE_URL}/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:
                    stats["solved"] += 1
                    return poll_result["request"]

                if poll_result.get("request") != "CAPCHA_NOT_READY":
                    stats["failed"] += 1
                    return None

                await asyncio.sleep(POLL_INTERVAL)

            stats["failed"] += 1
            return None

        except Exception as e:
            stats["failed"] += 1
            return None

async def run_batch(tasks):
    """Process a batch of CAPTCHA tasks concurrently."""
    connector = aiohttp.TCPConnector(
        limit=MAX_CONCURRENT,
        keepalive_timeout=60,
    )
    async with aiohttp.ClientSession(connector=connector) as session:
        coros = [
            solve_one(session, task["sitekey"], task["pageurl"], i)
            for i, task in enumerate(tasks)
        ]
        results = await asyncio.gather(*coros)
    return results

async def main():
    # Generate test tasks (replace with your task source)
    tasks = [
        {
            "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
            "pageurl": "https://www.google.com/recaptcha/api2/demo",
        }
        for _ in range(100)  # Start with 100 tasks
    ]

    stats["start"] = time.time()
    print(f"Processing {len(tasks)} tasks with {MAX_CONCURRENT} concurrent workers")

    results = await run_batch(tasks)
    elapsed = time.time() - stats["start"]

    print(f"\nCompleted in {elapsed:.0f}s")
    print(f"Submitted: {stats['submitted']}")
    print(f"Solved: {stats['solved']}")
    print(f"Failed: {stats['failed']}")
    print(f"Throughput: {stats['solved'] / (elapsed / 3600):.0f} solves/hour")

asyncio.run(main())

JavaScript: pipeline concorrente com Node.js

A mesma lógica em Node.js, com axios sobre um https.Agent de keep-alive para reaproveitar conexões TCP/TLS entre requisições:

// high_throughput_solver.js
const axios = require('axios');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
const BASE = 'https://ocr.captchaai.com';
const MAX_CONCURRENT = 50;

const agent = new https.Agent({ keepAlive: true, maxSockets: MAX_CONCURRENT });
const api = axios.create({ baseURL: BASE, httpsAgent: agent, timeout: 30000 });

const stats = { submitted: 0, solved: 0, failed: 0 };

async function solveOne(sitekey, pageurl) {
  try {
    const submit = await api.get('/in.php', {
      params: { key: API_KEY, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: '1' },
    });
    if (submit.data.status !== 1) { stats.failed++; return null; }
    stats.submitted++;

    await new Promise(r => setTimeout(r, 12000));

    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) { stats.solved++; return poll.data.request; }
      if (poll.data.request !== 'CAPCHA_NOT_READY') { stats.failed++; return null; }
      await new Promise(r => setTimeout(r, 5000));
    }
    stats.failed++;
    return null;
  } catch { stats.failed++; return null; }
}

async function runWithConcurrency(tasks, limit) {
  const results = [];
  const executing = new Set();

  for (const task of tasks) {
    const p = solveOne(task.sitekey, task.pageurl).then(r => {
      executing.delete(p);
      return r;
    });
    executing.add(p);
    results.push(p);

    if (executing.size >= limit) {
      await Promise.race(executing);
    }
  }
  return Promise.all(results);
}

(async () => {
  const tasks = Array.from({ length: 100 }, () => ({
    sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
    pageurl: 'https://www.google.com/recaptcha/api2/demo',
  }));

  const start = Date.now();
  console.log(`Processing ${tasks.length} tasks, ${MAX_CONCURRENT} concurrent`);

  await runWithConcurrency(tasks, MAX_CONCURRENT);
  const elapsed = (Date.now() - start) / 1000;

  console.log(`\nDone in ${elapsed.toFixed(0)}s`);
  console.log(`Solved: ${stats.solved}, Failed: ${stats.failed}`);
  console.log(`Throughput: ${(stats.solved / (elapsed / 3600)).toFixed(0)} solves/hour`);

  agent.destroy();
})();

Como monitorar a produtividade em tempo real

Antes de tocar em qualquer parâmetro, acompanhe estas métricas continuamente:

  • Resoluções por minuto — deve ficar perto de 167 para bater a meta de 10.000/hora
  • Taxa de erro — mantenha abaixo de 5%; se subir, reduza a simultaneidade
  • Profundidade da fila — se estiver crescendo, adicione workers; se estiver vazia, você está superprovisionado
  • Tempo de resolução P90 — se estiver subindo, a CaptchaAI pode estar limitando a taxa de requisições

Se os seus workers rodam na região sa-east-1 (São Paulo) da AWS, meça o RTT até o endpoint da CaptchaAI antes de subir o MAX_CONCURRENT — round-trip mais alto reduz a produtividade real por thread, mesmo com a concorrência configurada corretamente.

Dica: é mais barato descobrir um proxy lento ou uma região de rede ruim medindo RTT do que subir MAX_CONCURRENT às cegas e só depois investigar por que a taxa de erro disparou.

Parâmetros de ajuste para escalar a simultaneidade

Com as métricas acima sob controle, ajuste a simultaneidade em etapas:

Parâmetro Conservador Equilibrado Agressivo
MAX_CONCURRENT 20 50 100
INITIAL_WAIT 15 s 12 s 10 s
POLL_INTERVAL 7 s 5 s 3 s
MAX_POLL_ATTEMPTS 30 25 20
Taxa de transferência esperada ~4.800/h ~10.000/h ~18.000/h

Comece pelo cenário conservador e aumente MAX_CONCURRENT até ver retornos decrescentes ou a taxa de erro subir.

Solução de problemas comuns no pipeline

  • Produtividade estabiliza perto de 5.000/h — normalmente é simultaneidade insuficiente; aumente MAX_CONCURRENT para 80–100
  • Taxa de erro acima de 10% — a API está sobrecarregada ou os proxies estão ruins; reduza a simultaneidade e verifique a saúde dos proxies
  • Uso de memória crescendo sem parar — acúmulo de tarefas sem limite; processe os resultados assim que chegam, sem buffer
  • ERROR_NO_SLOT_AVAILABLE — a fila da CaptchaAI está cheia; aguarde e tente novamente após 5 segundos

Perguntas frequentes

Quantas threads da CaptchaAI eu preciso para bater 10.000 CAPTCHAs por hora?

Depende do seu tempo médio de resolução. Com a mediana de 15 s do reCAPTCHA v2, ~42 threads simultâneas bastam — o plano ADVANCE (US$ 90/mês, 50 threads) cobre isso com folga. Para tipos mais lentos ou picos de tráfego, considere o CORPORATE (US$ 240/mês, 150 threads).

A API da CaptchaAI tem algum limite de simultaneidade?

Não há um limite rígido de requisições simultâneas, mas uma concorrência muito alta (acima de 500) pode acionar limitação de taxa. Comece em 50 e vá subindo aos poucos.

Minha produtividade travou bem abaixo de 10 mil/hora — o que verificar primeiro?

Normalmente é MAX_CONCURRENT baixo demais ou proxies lentos inflando o tempo de resolução real. Confira a taxa de erro e a profundidade da fila antes de qualquer outro ajuste — se a fila está vazia, o gargalo é a geração de tarefas, não a API.

Rodar o pipeline em vários servidores consome mais saldo?

Não. O saldo é consumido por resolução, não por servidor ou por worker. Distribuir o pipeline entre máquinas com uma fila compartilhada (Redis, RabbitMQ) só distribui a carga de rede — o consumo total de créditos depende apenas de quantas soluções você processa.

Próximos passos

Monte seu pipeline de alta produtividade — obtenha sua chave de API da CaptchaAI.

Guias relacionados:

Os comentários estão desativados para este artigo.