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.
- Enviar los datos del CAPTCHA a
in.php - Guardar el ID de la tarea que devuelve la respuesta
- Sondear
res.phpcada 5 segundos hasta que el resultado esté listo - Usar el token — inyectarlo en el formulario o en la solicitud de destino
Paso 0: crea la cuenta y copia tu API key
- Regístrate en captchaai.com
- Entra en tu panel de control
- 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-sitekeyo en el script de Turnstile; empieza por0x - 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_READYse 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:
- Tu test detecta el widget en tu aplicación: QA, staging o preproducción.
- Envía a CaptchaAI los datos públicos del widget —
sitekey, URL y tipo de CAPTCHA. - CaptchaAI devuelve un token válido para esa página.
- Tu test escribe el token en el campo correspondiente y envía el formulario.
- 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
- Cómo resolver reCAPTCHA v2 con la API paso a paso
- Cómo resolver Cloudflare Turnstile con la API
- Cómo resolver GeeTest v3 con la API
- Resolución de CAPTCHA de imagen con la API
Crea tu cuenta en CaptchaAI y valida tu primera integración de CAPTCHA en tu propio entorno hoy mismo.