Referencia

Benchmark de tiempos de resolución de CAPTCHA con CaptchaAI

¿Cuánto tarda CaptchaAI en resolver un CAPTCHA? Depende del tipo: un reCAPTCHA v3 se despacha en pocos segundos, mientras que un reCAPTCHA v2 con imágenes puede acercarse al medio minuto. Esa diferencia, pequeña por resolución, se convierte en horas de cola con miles de tareas al día. Esta referencia reúne los tiempos observados por tipo con CaptchaAI, explica qué los mueve y te da scripts en Python y JavaScript para medir tu propio entorno.

Tiempos de resolución observados por tipo

La tabla resume la mediana y los percentiles de 100 resoluciones consecutivas por tipo, del envío por API a la recuperación del resultado. El límite de especificación es el techo del SLA; la mediana y los percentiles son observados con proxies realistas.

Tipo de CAPTCHA Límite de especificación Mediana P90 P99 Tasa de éxito
reCAPTCHA v2 <60s 12–18s 25s 40s Alta
reCAPTCHA v2 Invisible <30s 10–15s 20s 28s Alta
reCAPTCHA v3 <4s 1–3s 3s 4s Alta
reCAPTCHA Enterprise <60s 15–25s 35s 50s Alta
Cloudflare Turnstile <10s 4–8s 9s 10s Alta
GeeTest v3 <12s 6–10s 11s 12s Alta
Imagen/OCR <0.5s 0.2–0.4s 0.5s 0.8s Alta
BLS CAPTCHA <1s 0.3–0.7s 0.9s 1s Alta

La mediana y los percentiles son observados y varían según el proxy, la carga del servidor y la complejidad del CAPTCHA. El límite de especificación es el techo contractual del SLA: si ves resoluciones más lentas de forma sostenida, abre un ticket de soporte.

Cómo interpretar la mediana, el P90 y el P99

  • Mediana: la experiencia típica. Úsala para planificar capacidad.
  • P90: el "peor caso" de 9 de cada 10 resoluciones. Es la referencia para el timeout estándar.
  • P99: el caso límite real. Fija tu timeout máximo por encima de este número.

Regla práctica: parte del P90 para el timeout normal y del P99 para el máximo, con un margen del 20 % para la red.

Qué factores alteran el tiempo de resolución

  • Latencia de red. La distancia entre tu servidor y los endpoints de la API de CaptchaAI añade latencia de ida y vuelta; un RTT de 200 ms suma alrededor de 1 segundo (envío + 3 o 4 sondeos × 200 ms). Si tu backend corre en Frankfurt o São Paulo y monitorizas portales de cita previa o haces QA de un checkout regional, mide desde la misma región donde despliegas.
  • Calidad del proxy. Los proxies residenciales suelen dar tiempos más bajos que los de centro de datos porque activan menos desafíos secundarios; uno lento o lejano añade varios segundos. Mide con y sin proxy por separado.
  • Complejidad del CAPTCHA. Los desafíos de imagen de reCAPTCHA v2 varían en dificultad: un "selecciona los semáforos" con imágenes difusas tarda más que una casilla simple, así que un mismo tipo tiene mediana estable y P99 mucho más alto.
  • Estrategia de sondeo. El sondeo agresivo (cada 2 segundos) detecta el resultado antes pero multiplica las llamadas a la API; el conservador (cada 10 segundos) reduce la carga a costa de latencia.

Script de benchmark en Python

# benchmark_captchaai.py
import os
import time
import statistics
import requests

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")

def benchmark_solve(method, params, runs=10):
    """Benchmark a CAPTCHA type over multiple runs."""
    times = []
    successes = 0

    for i in range(runs):
        start = time.time()

        # Submit
        submit_params = {"key": API_KEY, "json": "1", **params}
        resp = requests.get("https://ocr.captchaai.com/in.php",
                            params=submit_params)
        result = resp.json()

        if result.get("status") != 1:
            print(f"  Run {i+1}: Submit failed - {result.get('request')}")
            continue

        task_id = result["request"]

        # Poll
        time.sleep(10)
        solved = False
        for _ in range(30):
            poll = requests.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:
                elapsed = time.time() - start
                times.append(elapsed)
                successes += 1
                solved = True
                print(f"  Run {i+1}: {elapsed:.1f}s")
                break
            if poll_result.get("request") != "CAPCHA_NOT_READY":
                print(f"  Run {i+1}: Error - {poll_result.get('request')}")
                break

            time.sleep(5)

        if not solved and poll_result.get("request") == "CAPCHA_NOT_READY":
            print(f"  Run {i+1}: Timeout")

    if times:
        return {
            "runs": runs,
            "successes": successes,
            "success_rate": f"{successes/runs*100:.0f}%",
            "median": f"{statistics.median(times):.1f}s",
            "p90": f"{sorted(times)[int(len(times)*0.9)]:.1f}s" if len(times) >= 10 else "N/A",
            "min": f"{min(times):.1f}s",
            "max": f"{max(times):.1f}s",
        }
    return {"error": "No successful solves"}

# Benchmark reCAPTCHA v2
print("=== reCAPTCHA v2 ===")
recaptcha_v2 = benchmark_solve("userrecaptcha", {
    "method": "userrecaptcha",
    "googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
    "pageurl": "https://www.google.com/recaptcha/api2/demo",
})
print(recaptcha_v2)

# Benchmark Image/OCR
print("\n=== Image CAPTCHA ===")
# Submit a base64-encoded test image
import base64
# Use a test image for benchmarking
image_result = benchmark_solve("post", {
    "method": "base64",
    "body": "BASE64_ENCODED_CAPTCHA_IMAGE",
})
print(image_result)

Script de benchmark en JavaScript

// benchmark_captchaai.js
const axios = require('axios');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';

async function benchmarkSolve(params, runs = 10) {
  const times = [];
  let successes = 0;

  for (let i = 0; i < runs; i++) {
    const start = Date.now();

    // Submit
    const submit = await axios.get('https://ocr.captchaai.com/in.php', {
      params: { key: API_KEY, json: '1', ...params },
    });

    if (submit.data.status !== 1) {
      console.log(`  Run ${i + 1}: Submit failed - ${submit.data.request}`);
      continue;
    }

    // Poll
    await new Promise(r => setTimeout(r, 10000));
    let solved = false;

    for (let j = 0; j < 30; j++) {
      const poll = await axios.get('https://ocr.captchaai.com/res.php', {
        params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
      });

      if (poll.data.status === 1) {
        const elapsed = (Date.now() - start) / 1000;
        times.push(elapsed);
        successes++;
        solved = true;
        console.log(`  Run ${i + 1}: ${elapsed.toFixed(1)}s`);
        break;
      }
      if (poll.data.request !== 'CAPCHA_NOT_READY') {
        console.log(`  Run ${i + 1}: Error - ${poll.data.request}`);
        break;
      }
      await new Promise(r => setTimeout(r, 5000));
    }

    if (!solved) console.log(`  Run ${i + 1}: Timeout`);
  }

  if (times.length === 0) return { error: 'No successful solves' };

  times.sort((a, b) => a - b);
  return {
    runs, successes,
    successRate: `${((successes / runs) * 100).toFixed(0)}%`,
    median: `${times[Math.floor(times.length / 2)].toFixed(1)}s`,
    min: `${times[0].toFixed(1)}s`,
    max: `${times[times.length - 1].toFixed(1)}s`,
  };
}

(async () => {
  console.log('=== reCAPTCHA v2 ===');
  const v2 = await benchmarkSolve({
    method: 'userrecaptcha',
    googlekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
    pageurl: 'https://www.google.com/recaptcha/api2/demo',
  });
  console.log(v2);

  console.log('\n=== Cloudflare Turnstile ===');
  const turnstile = await benchmarkSolve({
    method: 'turnstile',
    sitekey: 'YOUR_TURNSTILE_SITEKEY',
    pageurl: 'https://example.com',
  });
  console.log(turnstile);
})();

Ambos scripts envían la tarea, esperan un arranque inicial y sondean a intervalos fijos, guardando el tiempo total. Sube runs a 50 o más para estabilizar los percentiles.

Intervalos de sondeo recomendados por tipo

Configuración de partida según los tiempos observados: empieza a sondear justo antes de que el resultado esté listo.

Tipo de CAPTCHA Espera inicial Intervalo de sondeo Intentos máximos
Imagen/OCR 5s 3s 15
Cloudflare Turnstile 5s 3s 15
BLS CAPTCHA 5s 3s 15
reCAPTCHA v2 15s 5s 20
reCAPTCHA v3 10s 5s 20
GeeTest v3 12s 5s 20
reCAPTCHA Enterprise 15s 5s 25

Resolución de problemas

  • Tiempos por encima de lo indicado (latencia de red o proxy deficiente): mide desde una región más cercana a los servidores de CaptchaAI.
  • Resultados dispares entre ejecuciones (variación de dificultad del CAPTCHA): sube el tamaño de muestra a más de 50 ejecuciones.
  • Muchos tiempos de espera agotados (sitekey o URL de página no válidos): verifica los parámetros con una sola prueba manual.
  • ERROR_ZERO_BALANCE durante el benchmark (saldo insuficiente): recarga antes de lanzar pruebas grandes.

Preguntas frecuentes

¿Cuántas ejecuciones necesito para que el benchmark sea fiable?

Con 10 tienes una foto orientativa, pero la mediana y sobre todo el P90/P99 solo se estabilizan a partir de unas 50. Sube runs a 50–100 por tipo antes de decidir timeouts.

¿Por qué reCAPTCHA v2 tarda mucho más que Turnstile?

Porque son desafíos distintos: Turnstile se resuelve casi en silencio, mientras que reCAPTCHA v2 puede exigir varios pasos de imagen. No es una incidencia, es la naturaleza de cada tipo; por eso cada uno merece su timeout.

¿El benchmark consume saldo de mi cuenta?

Sí. Cada resolución del benchmark es una tarea real y descuenta de tus threads como cualquier otra. Antes de tandas grandes, confirma que hay saldo suficiente para evitar un ERROR_ZERO_BALANCE a mitad de la prueba.

Artículos relacionados

Ejecuta los scripts de benchmark contra tu propia cuenta y tus objetivos CAPTCHA. Obtén tu API key de CaptchaAI.

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