Solución de Problemas

Errores comunes de reCAPTCHA v2 Enterprise y cómo solucionarlos

Si la API devuelve un token válido y aun así el formulario responde "verificación fallida", el problema no está en la resolución: está en cómo enviaste la tarea. El fallo número uno es tratar un widget Enterprise como si fuera un v2 estándar. Sin enterprise=1, CaptchaAI lo resuelve como v2 normal y el backend — que verifica contra la API de Enterprise — descarta el token sin explicación.

El catálogo es corto: aquí van síntoma por síntoma, con el código que los corrige. Si dudas de la variante, empieza por cómo identificar una implementación de reCAPTCHA Enterprise.


Antes de depurar: confirma si es Enterprise o v2 estándar

Depurar la variante equivocada cuesta horas. Las diferencias:

Característica v2 estándar v2 Enterprise
URL del script google.com/recaptcha/api.js google.com/recaptcha/enterprise.js
Objeto JS grecaptcha grecaptcha.enterprise
Endpoint de verificación recaptcha/api/siteverify recaptchaenterprise.googleapis.com
Parámetro CaptchaAI method=userrecaptcha method=userrecaptcha + enterprise=1
Parámetro data-s Nunca A veces presente (token extra)

Dos comprobaciones en la consola zanjan la duda:

  • typeof grecaptcha.enterprise devuelve "object" en Enterprise, "undefined" en el estándar.
  • El método de envío no cambia: sigue siendo userrecaptcha.

Fallo 1: el sitio rechaza un token que la API entregó correctamente

Síntoma: in.php responde con estado 1, res.php devuelve el token y el formulario lo rechaza.

Causa: enviaste la tarea sin enterprise=1. El token es legítimo, pero de la familia equivocada.

Solución: añade el flag:

import requests

response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "6LcR_RsTAAAAAFJR-JhNbC6CC42wKCbR9Hq_kVCd",
    "pageurl": "https://staging.example.com/qa-login",
    "enterprise": 1,
    "json": 1
})

data = response.json()
task_id = data["request"]

El equivalente en Node.js:

const params = new URLSearchParams({
  key: "YOUR_API_KEY",
  method: "userrecaptcha",
  googlekey: "6LcR_RsTAAAAAFJR-JhNbC6CC42wKCbR9Hq_kVCd",
  pageurl: "https://staging.example.com/qa-login",
  enterprise: 1,
  json: 1,
});

const res = await fetch(`https://ocr.captchaai.com/in.php?${params}`);
const data = await res.json();
const taskId = data.request;

Fallo 2: falta el parámetro data-s

Síntoma: ERROR_BAD_PARAMETERS, o el token sigue rechazado pese a llevar enterprise=1.

Causa: algunas implementaciones Enterprise añaden al div un atributo data-s, un token de sesión del desafío. Si la página lo publica y no lo reenvías, la verificación falla.

Solución: inspecciona el div g-recaptcha y propaga el valor:

# Look for: <div class="g-recaptcha" data-sitekey="..." data-s="..."></div>
response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "enterprise": 1,
    "data-s": data_s_value,  # Include if present on the page
    "json": 1
})

Léelo del DOM en cada ejecución: cambia entre cargas de página.


Fallo 3: identificaste mal el script

Síntoma: el token funciona de forma intermitente.

Causa: el sitio migró, dejó ambos scripts en el HTML y clasificaste el widget al revés.

Solución: comprueba qué script y qué objeto JS renderizan el widget:

// Enterprise uses enterprise.js
// <script src="https://www.google.com/recaptcha/enterprise.js?render=SITEKEY"></script>

// Standard uses api.js
// <script src="https://www.google.com/recaptcha/api.js"></script>

// Also check the JS object:
// Enterprise: grecaptcha.enterprise.render(...)
// Standard: grecaptcha.render(...)

Errores generales que comparte con el v2 estándar

Descartado lo anterior, quedan los códigos habituales:

Código de error Causa Solución
ERROR_WRONG_USER_KEY Formato de clave no válido Verifícala en captchaai.com/api.php
ERROR_KEY_DOES_NOT_EXIST Clave no encontrada Busca espacios perdidos al copiarla
ERROR_ZERO_BALANCE Sin saldo Recarga tu cuenta
ERROR_PAGEURL Falta pageurl Envía la URL completa
ERROR_GOOGLEKEY Sitekey mal formado Extráelo otra vez de data-sitekey
ERROR_BAD_TOKEN_OR_PAGEURL Sitekey y URL no coinciden Revisa el contexto del iframe
CAPCHA_NOT_READY Todavía en proceso Espera 5 segundos y vuelve a sondear
ERROR_CAPTCHA_UNSOLVABLE No se pudo resolver Envía una tarea nueva

Un caso habitual: portales de cita previa y trámites públicos

En portales administrativos hispanohablantes — cita previa, trámites tipo SAT, centros de visados BLS — el patrón se repite: el equipo prueba en staging contra un widget v2 estándar, todo funciona, y al pasar al portal real los tokens rebotan. La diferencia era una línea: el portal servía enterprise.js.

Detecta la variante en tiempo de ejecución, no por entorno, y respeta los términos de servicio y la normativa de protección de datos aplicable. CaptchaAI factura por threads concurrentes: BASIC ($15/mes, 5 threads) cubre el QA de un equipo pequeño y ADVANCE ($90/mes, 50 threads), pipelines en paralelo.


Flujo completo de resolución con manejo de errores

Móntalo una vez: envía, sondea y distingue "aún no está listo" de "falló de verdad".

import requests
import time

def solve_recaptcha_v2_enterprise(api_key, sitekey, page_url, data_s=None):
    params = {
        "key": api_key,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": page_url,
        "enterprise": 1,
        "json": 1
    }
    if data_s:
        params["data-s"] = data_s

    response = requests.get("https://ocr.captchaai.com/in.php", params=params)
    data = response.json()

    if data.get("status") != 1:
        raise RuntimeError(f"Submit failed: {data.get('request')}")

    task_id = data["request"]

    for _ in range(40):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key, "action": "get", "id": task_id, "json": 1
        }).json()

        if result.get("status") == 1:
            return result["request"]
        if result.get("request") == "CAPCHA_NOT_READY":
            continue
        raise RuntimeError(f"Solve failed: {result.get('request')}")

    raise TimeoutError("Solve timed out after 200 seconds")

token = solve_recaptcha_v2_enterprise("YOUR_API_KEY", "SITEKEY", "https://staging.example.com/qa-login")

Lo mismo en Node.js:

async function solveRecaptchaV2Enterprise(apiKey, sitekey, pageUrl, dataS) {
  const params = new URLSearchParams({
    key: apiKey, method: "userrecaptcha", googlekey: sitekey,
    pageurl: pageUrl, enterprise: 1, json: 1,
  });
  if (dataS) params.set("data-s", dataS);

  const submitRes = await fetch(`https://ocr.captchaai.com/in.php?${params}`);
  const submitData = await submitRes.json();
  if (submitData.status !== 1) throw new Error(`Submit failed: ${submitData.request}`);

  const taskId = submitData.request;
  for (let i = 0; i < 40; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const res = await fetch(`https://ocr.captchaai.com/res.php?${new URLSearchParams({
      key: apiKey, action: "get", id: taskId, json: 1,
    })}`);
    const data = await res.json();
    if (data.status === 1) return data.request;
    if (data.request === "CAPCHA_NOT_READY") continue;
    throw new Error(`Solve failed: ${data.request}`);
  }
  throw new Error("Timed out after 200s");
}

El techo son 200 segundos (40 intentos por 5). Si rozas ese límite, revisa sitekey y pageurl antes que el timeout.


Preguntas frecuentes

Lo que más se pregunta sobre Enterprise:

¿Cuánto dura un token de reCAPTCHA v2 Enterprise antes de caducar?

Unos dos minutos, igual que en el v2 estándar. Envía el formulario justo después de recibirlo.

¿Puedo reutilizar un token Enterprise en varias solicitudes?

No. Es de un solo uso y va ligado al par sitekey + pageurl de esa carga.

Si los pones en cola, caducan esperando turno.

¿Cambia el precio por resolver Enterprise en lugar del v2 estándar?

No. CaptchaAI factura por threads concurrentes, con resoluciones ilimitadas dentro del plan y sin recargos por tipo de CAPTCHA.

¿Qué hago si data-s no aparece en el HTML?

Esa implementación no lo usa: omítelo. Enviarlo vacío provoca ERROR_BAD_PARAMETERS.

Vuelve a mirar tras renderizar el JS: a veces se inyecta después.

¿Sirve el mismo código para v2 estándar y Enterprise?

Sí. Cambia solo el flag; método, parámetros y sondeo son idénticos.


Lista de verificación antes de abrir un ticket

Casi todos los tickets Enterprise se cierran en uno de estos puntos.

  1. Confirma la variante buscando enterprise.js en las etiquetas <script>.
  2. Añade enterprise=1 si el widget es Enterprise.
  3. Comprueba data-s en el div g-recaptcha.
  4. Envía el token antes de los ~2 minutos.
  5. Verifica sitekey y pageurl, sobre todo dentro de un iframe.

Guías relacionadas

Obtén tu clave API en captchaai.com/api.php y valida un token Enterprise contra tu staging antes de tocar producción.

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