Tutoriales de API

Cómo resolver reCAPTCHA v2 con la API: guía paso a paso

¿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 iframehttps://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=1 al 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-callback e 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-Agent que estaban activos cuando pediste el token.
  • El reto depende de la IP — añade los parámetros proxy y proxytype en 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

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