Tutoriales de API

Optimización de latencia API CaptchaAI: resoluciones más rápidas

Para bajar el tiempo que tu proceso espera por cada token, dos cambios rinden más que cualquier otro: solapa el envío de la tarea con el trabajo que ya estás haciendo y deja de esperar en bloques fijos de 5 segundos. Ninguno toca el solver: la ganancia está en tu lado de la conexión.


Los cuatro tramos de una resolución

Cada token atraviesa cuatro tramos y solo uno queda fuera de tu alcance:

  • Envío de la tarea a in.php: milisegundos, salvo que abras una conexión nueva cada vez.
  • Espera en cola: según cuántos threads de tu plan estén ocupados.
  • Ejecución del solver: el único tramo que no controlas.
  • Recuperación del resultado desde res.php o vía pingback: aquí pierde tiempo la mayoría de los pipelines.

Tres de los cuatro son tuyos.


Por dónde empezar si solo vas a tocar una cosa

Ordena el trabajo por lo que devuelve cada cambio, no por lo rápido de escribir:

  1. Solapa la resolución con tu procesamiento. El prefetch elimina casi toda la espera percibida.
  2. Cambia cómo recuperas el resultado. Sondeo adaptativo o pingback en vez del bloque fijo de 5 segundos.
  3. Afina transporte y envío. Keep-alive, parámetros por tipo de CAPTCHA y proxy solo si hace falta.

1. Ajusta el intervalo de sondeo en vez de fijarlo en 5 s

El intervalo fijo de 5 segundos desperdicia tiempo cuando la resolución termina justo después de un sondeo. Consulta cada 3 segundos y amplía el intervalo si la tarea se alarga.

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`);
}
  • Ahorro típico: entre 1 y 4 segundos por tarea frente al intervalo fijo.
  • Suelo recomendado: 3 segundos. Por debajo no adelantas nada y te acercas al límite.

2. Reutiliza conexiones con keep-alive

Cada sondeo que abre una conexión nueva paga handshakes TCP y TLS completos. Con una sesión reutilizable esa factura desaparece:

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

Son 50–100 ms por solicitud: poco, hasta multiplicarlo por los cinco o seis sondeos de cada tarea.


3. Envía la tarea antes de necesitar el token

El prefetch es la optimización con mejor relación esfuerzo/resultado: mientras tu scraper procesa la página N, envía el CAPTCHA de la N+1.

Python

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)
  • La resolución corre en paralelo con tu procesamiento: en flujos secuenciales la espera percibida tiende a cero.
  • No adelantes tanto el envío que el token caduque antes de usarlo.

4. Elige el método de envío adecuado

En algunos escenarios hay una vía más corta que la genérica:

Escenario Método lento Alternativa más rápida
reCAPTCHA v2 con callback conocido userrecaptcha + sondeo userrecaptcha con pingback (URL de callback)
CAPTCHA de texto en imagen base64 a máxima resolución base64 con numeric=1 si solo hay dígitos

Acotar el espacio de respuesta reduce el trabajo del solver sin tocar tu código.


5. Manda parámetros de proxy solo cuando el sitio lo exija

Enrutar por un proxy añade latencia. Manda esos parámetros solo si el destino exige una IP concreta:

Python

# 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:[email protected]:8080"
data["proxytype"] = "HTTP"

6. Sustituye el sondeo por un pingback

La forma más rápida de recuperar un resultado es no ir a buscarlo: con el parámetro pingback, CaptchaAI lo entrega a tu endpoint en cuanto termina la resolución.

Python

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

Desaparece el bucle de sondeo, pero necesitas un endpoint público: tras un firewall corporativo el resultado no llega y conviene seguir con el sondeo adaptativo.


7. Mide antes y después

Ninguna de estas técnicas se justifica sin números propios: instrumenta, aplica un cambio y vuelve a medir.

Python

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")
  • Mira la mediana y el P95: esta latencia tiene cola larga y el promedio la esconde.
  • Anota cuántos sondeos consumió cada tarea: delata un intervalo mal ajustado.

Techos de tiempo por tipo de CAPTCHA

Contrasta tus mediciones con los límites de servicio publicados:

Tipo de CAPTCHA Techo publicado Rango realista optimizado
Imagen/OCR <0.5 s 0.2–0.4 s
reCAPTCHA v2 <60 s 10–20 s
reCAPTCHA v3 <4 s 1–3 s
Cloudflare Turnstile <10 s 4–8 s
GeeTest v3 <12 s 6–10 s

La segunda columna es lo que suele verse tras aplicar lo anterior. Si superas el techo con holgura, el problema rara vez está en el solver: está en tu bucle de recuperación.


Cómo se ve esto en un pipeline real

Un equipo en Ciudad de México monitorea precios en marketplaces regionales desde un servidor en São Paulo. Su scraper se bloqueaba en cada reCAPTCHA v2 hasta recibir el token, y abría una conexión nueva en cada sondeo.

Al enviar el CAPTCHA de la página siguiente antes de terminar la actual, sondear a 3 segundos con retroceso y compartir una sola sesión HTTP, la resolución ocurre mientras el proceso ya hace otra cosa. Siguen en ADVANCE ($90/mes, 50 threads); lo que cambió es cuántos threads están ocupados a la vez.

  • Mide desde la región donde corre tu carga real: la distancia hasta los endpoints añade una ida y vuelta a cada llamada.
  • Respeta los términos de servicio del sitio y la normativa de protección de datos aplicable (GDPR y LOPDGDD en España, LFPDPPP en México).

Diagnóstico rápido cuando la latencia no baja

Si aplicaste todo y el reloj no se mueve, revisa estos cuatro sospechosos:

Síntoma Causa habitual Qué hacer
El sondeo tarda igual que antes Sigues llamando a requests.get() sin sesión Cambia a session.get()
El token del prefetch caduca antes de usarlo El procesamiento intermedio dura demasiado Acorta la ventana
La URL de pingback no recibe nada El endpoint no es público Publícalo y revisa las reglas del firewall
Aparecen errores de límite de solicitudes Sondeo por debajo de 2 s Mantén el mínimo en 3 s

Preguntas frecuentes

¿Contratar más threads reduce la latencia de una resolución?

No. Los threads determinan cuántas tareas tienes en vuelo a la vez, no lo que tarda cada una. Si hay espera en cola, más threads ayudan; si la resolución es lenta, mira el sondeo y el prefetch.

¿Cuál es el intervalo de sondeo mínimo razonable?

Tres segundos. Por debajo multiplicas llamadas sin adelantar la resolución y te expones al límite.

¿Influye la región de mi servidor en el tiempo total?

Sí, aunque es el factor menor: la distancia añade una ida y vuelta a cada llamada, y con keep-alive ese coste se paga muchas menos veces.

¿Puedo combinar pingback y sondeo en el mismo pipeline?

Sí, y es lo más robusto: usa pingback como vía principal y deja un sondeo de respaldo, con intervalo amplio, para los callbacks que no lleguen.


Empieza a medir tu latencia real

Obtén tu clave API en captchaai.com, corre el benchmark de arriba y compara mediana y P95 antes y después del prefetch.


Guías relacionadas

Los comentarios están deshabilitados para este artículo.