¿Tu automatización se detiene en la casilla «No soy un robot»? No hace falta resolver la cuadrícula de imágenes a mano ni imitar el comportamiento del ratón: le pasas dos datos a una API, esperas unos segundos y recibes un token válido para inyectar en el formulario. Ese es todo el mecanismo.
El flujo se reduce a cuatro pasos: extraes el sitekey y el pageurl de la página, los envías al solver de reCAPTCHA v2 de CaptchaAI, sondeas hasta que el resultado está listo e inyectas el token en el flujo protegido. Abajo tienes el código funcional en Python y Node.js, junto con los errores que más tiempo hacen perder.
En la práctica este patrón aparece cuando un equipo automatiza las pruebas de su propio flujo de login o monitorea un portal público protegido —un panel de trámites, un formulario de alta— y necesita que el pipeline no se frene ante cada reCAPTCHA. Con un plan BASIC ($15/mes, 5 threads) resuelves varios retos en paralelo sin pagar por resolución. Como siempre, respeta los términos de servicio y la normativa de protección de datos aplicable.
¿No sabes qué versión de reCAPTCHA tienes delante? Empieza por cómo identificar la versión de reCAPTCHA.
Antes de empezar: lo que necesitas a mano
| Requisito | Detalle |
|---|---|
| API key de CaptchaAI | La obtienes en captchaai.com/api.php; es una cadena de 32 caracteres. |
| URL completa | La dirección exacta donde se carga el widget de reCAPTCHA v2, con https://. |
| sitekey | La clave pública del widget en esa página concreta. |
| Cliente HTTP | requests, axios, fetch o curl — el que ya uses. |
| Threads disponibles | Tu cuenta necesita threads libres para lanzar resoluciones. |
Paso 1: localiza el sitekey y el pageurl
Estos dos valores son la entrada de todo el proceso; equivocarse en uno de ellos es, con diferencia, el motivo más frecuente de que una resolución falle.
Dónde encontrar el sitekey
El sitekey es la clave pública que Google asigna al widget de esa página. Tienes tres vías para dar con él:
1. Directamente en el HTML — busca el contenedor <div class="g-recaptcha" data-sitekey="...">:
<div class="g-recaptcha" data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"></div>
2. En la URL del iframe — https://www.google.com/recaptcha/api2/anchor?ar=1&k=6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&.... El valor del parámetro k= es el sitekey.
3. En el tráfico de red — abre DevTools → Network, filtra por recaptcha y encontrarás el parámetro k en cualquiera de las peticiones.
Qué poner en el pageurl
El pageurl es la URL de la página donde aparece el reCAPTCHA. Pásala completa, con https:// incluido; una URL a medias es la primera causa de fallos silenciosos. Si el widget vive dentro de un iframe alojado en otro subdominio, usa la URL de ese iframe, no la de la página padre.
Paso 2: envía la tarea a la API
Envía el par sitekey + pageurl al endpoint in.php con method=userrecaptcha. La API te devuelve un identificador de tarea que usarás para consultar el resultado:
import requests
API_KEY = "YOUR_API_KEY"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
PAGEURL = "https://staging.example.com/qa-login"
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": SITEKEY,
"pageurl": PAGEURL,
"json": 1,
}).json()
assert submit["status"] == 1, submit
task_id = submit["request"]
print("task id:", task_id)
El equivalente en Node.js con fetch:
const r = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: SITEKEY,
pageurl: PAGEURL,
json: "1",
}),
});
const { status, request: taskId } = await r.json();
if (status !== 1) throw new Error(taskId);
¿Es un reCAPTCHA invisible? Añade
invisible=1al payload y el resto del flujo no cambia. Tienes el detalle en cómo funciona la reCAPTCHA invisible.
Paso 3: consulta el resultado (sondeo)
Un reCAPTCHA v2 suele resolverse en menos de 60 segundos con una alta tasa de éxito. No consultes de inmediato: espera unos 20 segundos y luego sondea res.php cada 5 hasta que el token esté listo.
import time
time.sleep(20)
while True:
res = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if res.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if res.get("status") == 1:
token = res["request"]
print("token:", token[:60], "…")
break
raise RuntimeError(res)
Mientras la respuesta sea CAPCHA_NOT_READY, la resolución sigue en curso: espera y vuelve a consultar. El token final es una cadena larga que suele empezar por 03AGdBq25....
Paso 4: inyecta el token en la página
Obtener el token es solo la mitad del trabajo: hay que entregárselo a la página tal y como ella lo espera.
Rellenar el campo g-recaptcha-response
Lo más habitual es escribir el token en el textarea oculto g-recaptcha-response y enviar el formulario:
document.querySelector('textarea[name="g-recaptcha-response"]').value = token;
document.querySelector("form").submit();
Con Selenium desde Python:
driver.execute_script(
"document.querySelector('[name=\"g-recaptcha-response\"]').value = arguments[0];",
token,
)
driver.find_element(By.CSS_SELECTOR, "form").submit()
Con Playwright:
await page.evaluate((t) => {
document.querySelector('[name="g-recaptcha-response"]').value = t;
}, token);
await page.click('button[type="submit"]');
Invocar la función callback
Si el widget declara un data-callback, rellenar el campo no basta: hay que invocar esa función con el token para que la página dé por válido el reto.
const callback = document.querySelector(".g-recaptcha").dataset.callback;
if (callback && window[callback]) window[callback](token);
Ejemplo completo en Python
Los fragmentos anteriores, reunidos en una función reutilizable con envío, espera inicial y sondeo con límite de intentos:
import time
import requests
API_KEY = "YOUR_API_KEY"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
PAGEURL = "https://staging.example.com/qa-login"
def solve_recaptcha_v2():
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": SITEKEY, "pageurl": PAGEURL, "json": 1,
}).json()
if submit["status"] != 1:
raise RuntimeError(submit)
task_id = submit["request"]
time.sleep(20)
for _ in range(40):
res = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}).json()
if res.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if res.get("status") == 1:
return res["request"]
raise RuntimeError(res)
raise TimeoutError("solve timed out")
if __name__ == "__main__":
token = solve_recaptcha_v2()
print("token:", token[:80])
Errores frecuentes y cómo resolverlos
| Error | Causa | Acción |
|---|---|---|
ERROR_GOOGLEKEY |
sitekey vacío o inválido | Vuelve a extraer el sitekey desde la página actual |
ERROR_PAGEURL |
Falta el pageurl |
Pásalo completo, con el esquema https:// |
ERROR_ZERO_BALANCE |
Sin threads libres | Recarga o espera a que se liberen threads |
ERROR_CAPTCHA_UNSOLVABLE |
El sitio endureció el reto | Reintenta a los pocos segundos; revisa los errores comunes al resolver reCAPTCHA v2 |
| El sitio rechaza el token | Token caducado | Úsalo dentro de los ~110 s siguientes a recibirlo |
Cuando el token no funciona
- La API devolvió el token pero el sitio sigue bloqueando — el formulario tiene su propio handler. Localiza el
data-callbacke invócalo en lugar de rellenar el textarea sin más. - Hay que mantener la misma sesión — envía las mismas cookies y el mismo
User-Agentque estaban activos cuando pediste el token. - El reto depende de la IP — añade los parámetros
proxyyproxytypeen el envío para que el solver use tu propia salida de red.
Preguntas frecuentes
¿Puedo resolver reCAPTCHA v2 sin abrir un navegador?
Sí. Si tu flujo no usa Selenium ni Playwright, incluye el token en el mismo POST que envía el formulario, dentro del campo g-recaptcha-response. El navegador solo es necesario cuando la página valida el reto con JavaScript del lado del cliente.
¿Cuánto cuesta resolver reCAPTCHA v2 a gran volumen?
CaptchaAI factura por threads concurrentes, no por resolución. El plan BASIC ($15/mes, 5 threads) incluye resoluciones ilimitadas; cuando tu volumen crezca, subes de plan para tener más threads en paralelo. Consulta los precios oficiales en captchaai.com/pricing.
¿Por qué el sitio rechaza el token aunque la API lo devolvió?
Casi siempre es un problema de inyección, no de la API: campo equivocado, un data-callback sin invocar o un token ya caducado. Verifica que rellenas g-recaptcha-response en el frame correcto y que lo usas dentro de sus ~110 segundos de validez.
¿Sirve el mismo código para reCAPTCHA v3 o Turnstile?
Sí, el patrón envío → sondeo → token es idéntico; solo cambian el method y algún parámetro. Puedes reaprovechar esta misma función para Cloudflare Turnstile y otros tipos que soporta CaptchaAI.
¿Necesito un proxy para resolver reCAPTCHA v2?
No es obligatorio. Añade proxy y proxytype solo cuando el sitio ligue el reto a la IP que lo originó; en la mayoría de los casos el envío directo funciona sin proxy.
Siguientes pasos
- Inicio rápido de CaptchaAI: tu primera resolución en 5 minutos
- Cómo identificar la versión de reCAPTCHA
- Cómo resolver Cloudflare Turnstile con la API
- Errores y correcciones comunes de reCAPTCHA v2