Primeros Pasos

Inicio rápido de CaptchaAI: tu primera resolución de CAPTCHA en 5 minutos

Resolver tu primer CAPTCHA con CaptchaAI son dos llamadas HTTP: una envía la tarea a in.php y otra recoge el token en res.php. El resto — lenguaje, framework, navegador headless o no — es decoración alrededor de ese par.

Abajo tienes la secuencia completa, con código para copiar en cURL, Python, Node.js y PHP. El ejemplo usa Cloudflare Turnstile porque es el tipo que antes devuelve token: su techo de servicio está en menos de 10 s.

El ciclo que siguen todos los tipos compatibles

Trabajes con reCAPTCHA v2, con Turnstile o con un CAPTCHA de imagen, el ciclo no cambia; solo los parámetros.

  1. Enviar los datos del CAPTCHA a in.php
  2. Guardar el ID de la tarea que devuelve la respuesta
  3. Sondear res.php cada 5 segundos hasta que el resultado esté listo
  4. Usar el token — inyectarlo en el formulario o en la solicitud de destino

Paso 0: crea la cuenta y copia tu API key

  1. Regístrate en captchaai.com
  2. Entra en tu panel de control
  3. Copia la API key de 32 caracteres

Tu cuenta necesita threads activos. CaptchaAI factura por thread concurrente, no por resolución: BASIC ($15/mes, 5 threads) mantiene cinco CAPTCHA en vuelo a la vez, con resoluciones ilimitadas. Si aún evalúas el servicio, pide una prueba gratuita a soporte.


Paso 1: envía el CAPTCHA a in.php

El ejemplo resuelve un Cloudflare Turnstile. Necesitas dos datos del HTML de la página:

  • sitekey — la clave pública del widget, en el atributo data-sitekey o en el script de Turnstile; empieza por 0x
  • pageurl — la URL completa, con protocolo, donde se carga el widget

Los cuatro fragmentos hacen lo mismo: elige el de tu stack.

cURL

curl -X POST "https://ocr.captchaai.com/in.php" \
  -d "key=YOUR_API_KEY" \
  -d "method=turnstile" \
  -d "sitekey=0x4AAAAAAAC3DHQFLr1GavNl" \
  -d "pageurl=https://staging.example.com/qa-login" \
  -d "json=1"

Python

import requests

response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "turnstile",
    "sitekey": "0x4AAAAAAAC3DHQFLr1GavNl",
    "pageurl": "https://staging.example.com/qa-login",
    "json": 1,
})
print(response.json())

Node.js

const response = await fetch("https://ocr.captchaai.com/in.php", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    key: "YOUR_API_KEY",
    method: "turnstile",
    sitekey: "0x4AAAAAAAC3DHQFLr1GavNl",
    pageurl: "https://staging.example.com/qa-login",
    json: "1",
  }),
});
console.log(await response.json());

PHP

<?php
$response = file_get_contents("https://ocr.captchaai.com/in.php?" . http_build_query([
    "key"       => "YOUR_API_KEY",
    "method"    => "turnstile",
    "sitekey"   => "0x4AAAAAAAC3DHQFLr1GavNl",
    "pageurl"   => "https://staging.example.com/qa-login",
    "json"      => 1,
]));
echo $response;

Paso 2: guarda el ID de la tarea

Si el envío entra bien, la respuesta es tan corta como esta:

{
  "status": 1,
  "request": "71823469"
}

El valor de request es el ID de la tarea: guárdalo, es lo único que la identifica.

Cuando status vale 0, request trae el código de error:

Error Qué significa Cómo se corrige
ERROR_WRONG_USER_KEY Formato de API key inesperado Comprueba los 32 caracteres
ERROR_KEY_DOES_NOT_EXIST La API key no existe Cópiala de nuevo desde tu panel
ERROR_ZERO_BALANCE No hay threads libres Amplía el plan o espera
ERROR_PAGEURL Falta el parámetro pageurl Añade la URL completa
ERROR_WRONG_GOOGLEKEY sitekey vacío o mal formado Extráelo otra vez del HTML

Paso 3: consulta el resultado en res.php

Espera 15 segundos antes del primer sondeo y consulta después cada 5 segundos. Antes solo devuelve CAPCHA_NOT_READY.

Python

import time

time.sleep(15)

while True:
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": "YOUR_API_KEY",
        "action": "get",
        "id": "71823469",
        "json": 1,
    }).json()

    if result.get("request") == "CAPCHA_NOT_READY":
        time.sleep(5)
        continue

    if result.get("status") == 1:
        token = result["request"]
        print(f"Solved! Token: {token[:60]}...")
        break

    raise RuntimeError(result)

Node.js

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

while (true) {
  const r = await fetch(
    `https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=get&id=71823469&json=1`,
  );
  const data = await r.json();
  if (data.request === "CAPCHA_NOT_READY") {
    await new Promise((r) => setTimeout(r, 5000));
    continue;
  }
  if (data.status === 1) {
    console.log("Solved:", data.request.slice(0, 60));
    break;
  }
  throw new Error(JSON.stringify(data));
}

Un Turnstile normal responde en el primer o segundo sondeo. Si CAPCHA_NOT_READY se repite más de un minuto, la tarea está atascada: cancélala y reenvíala.


Paso 4: inyecta el token donde lo espera la página

El token se escribe en el campo oculto que el widget dejó vacío. El nombre depende del tipo:

Tipo Dónde se escribe el token
Cloudflare Turnstile cf-turnstile-response, o el callback de la página
reCAPTCHA v2 y v3 g-recaptcha-response
Imagen u OCR El texto reconocido, en el input de respuesta
GeeTest v3 Varios campos que se ensamblan según el sitio

Inyección mínima desde el navegador:

document.querySelector('[name="cf-turnstile-response"]').value = token;
document.querySelector("form").submit();

Sin navegador, añade el token como un campo más del POST.


Un escenario cercano: portales públicos y trámites en línea

Buena parte de quien llega aquí trabaja sobre el mismo terreno:

  • Cita previa en portales de la administración española
  • Trámites del SAT en México y gestiones ante AFIP
  • Centros de visados BLS, con su propio BLS CAPTCHA

Son páginas que cambian sin avisar y rompen una suite de pruebas de un día para otro.

Ahí el patrón de cuatro pasos no cambia; cambia el calendario. Ejecuta el flujo completo contra tu staging en cada despliegue: un job diario que envía un Turnstile de prueba y comprueba que tu backend sigue validando el token detecta el problema antes que cualquier usuario. Y respeta los términos de servicio del portal y la normativa de protección de datos aplicable — GDPR y LOPDGDD en España, LFPDPPP en México.


Configuración de navegador idéntica en local y en CI

Usa la misma configuración de navegador en QA, staging y CI: la mitad de los "en mi máquina funciona" salen de un viewport o un idioma distintos entre tu portátil y el runner.

from selenium import webdriver

def make_driver(headless: bool = True) -> webdriver.Chrome:
    options = webdriver.ChromeOptions()
    if headless:
        options.add_argument('--headless=new')
    options.add_argument('--window-size=1280,800')
    options.add_argument('--lang=es-ES')
    return webdriver.Chrome(options=options)

Viewport, idioma y user-agent idénticos dejan comparables dos ejecuciones.

Cómo encaja CaptchaAI en tu pipeline

El patrón de integración no cambia según el lenguaje ni el framework de pruebas:

  1. Tu test detecta el widget en tu aplicación: QA, staging o preproducción.
  2. Envía a CaptchaAI los datos públicos del widget — sitekey, URL y tipo de CAPTCHA.
  3. CaptchaAI devuelve un token válido para esa página.
  4. Tu test escribe el token en el campo correspondiente y envía el formulario.
  5. Tu backend verifica el token contra el proveedor, igual que con una persona.

Este flujo se aplica a integraciones que tú controlas; no sirve para sortear protecciones de terceros. Instrumenta desde el principio el tiempo de resolución, la tasa de éxito de tu endpoint y la distribución de códigos ERROR_*: reproducir un fallo intermitente sin trazas es adivinar.

Qué falla el primer día y cómo se arregla

Síntoma Causa Arreglo
ERROR_WRONG_USER_KEY Espacio en blanco al copiar la API key Recorta la clave a 32 caracteres
ERROR_PAGEURL pageurl sin protocolo Escribe la URL completa con https://
CAPCHA_NOT_READY sin fin Primer sondeo demasiado pronto Espera 15 s y sondea cada 5 s
El destino responde HTTP 403 sitekey de otra página; van ligados a su URL Extráelo del HTML de esa misma URL
La API responde texto plano en vez de JSON Falta json=1 Añade json=1 al envío
El token se rechaza al reutilizarlo Los de Turnstile y reCAPTCHA son de un solo uso y caducan en unos 120 s Pide uno nuevo en cada envío
ERROR_ZERO_BALANCE o ERROR_NO_SLOT_AVAILABLE Sin threads libres Reintenta con retroceso exponencial o amplía el plan; ver códigos de error de la API
Tu backend rechaza el token action o sitekey no coinciden con el widget Compáralos con la configuración real
Pasa en local y falla en CI Viewport, idioma o user-agent distintos Iguala el navegador en ambos entornos
Tiempos de resolución dispares Concurrencia por encima de tus threads Revisa la capacidad de tu plan

Y un hábito que ahorra tiempo: una API key distinta para QA y para producción.

Preguntas frecuentes

¿Cuánto cuesta empezar y cómo se factura?

Depende de tu concurrencia, no del número de resoluciones. El plan BASIC ($15/mes, 5 threads) mantiene cinco CAPTCHA a la vez con resoluciones ilimitadas; STANDARD ($30/mes, 15 threads) es el salto natural cuando la cola se acumula.

¿Qué tipos de CAPTCHA acepta esta misma secuencia?

Los generalmente disponibles: reCAPTCHA v2 (invisible, callback y Enterprise incluidos), reCAPTCHA v3, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, imagen u OCR, grid-image y BLS CAPTCHA. CaptchaFox, Friendly Captcha y Lemin están en beta. hCaptcha y FunCaptcha (Arkose Labs) no son compatibles, y GeeTest v4 figura como próximamente.

¿Cuánto tarda en llegar el token?

Depende del tipo: Turnstile se resuelve normalmente en menos de 10 s y reCAPTCHA v2 tiene un techo de menos de 60 s. Con la espera inicial, un ciclo completo suele cerrarse en 15–30 segundos.

¿Puedo lanzar esto contra cualquier web?

No. Está pensado para tu propia aplicación y para entornos de QA o staging sobre los que tienes autorización explícita; hacerlo en sitios que no controlas puede infringir sus términos de servicio.

¿Qué hago si CAPCHA_NOT_READY no termina nunca?

Pon un límite: define un deadline, cancela la tarea al superarlo y reenvíala con retroceso exponencial. Una tarea atascada ocupa un thread que necesitas para la siguiente.

Siguientes pasos

Crea tu cuenta en CaptchaAI y valida tu primera integración de CAPTCHA en tu propio entorno hoy mismo.

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