Solución de Problemas

Errores y correcciones de verificación de dominio reCAPTCHA

reCAPTCHA valida que los tokens se utilicen en el mismo dominio para el que se generaron. Cuando hay una discrepancia entre la configuración del dominio de CAPTCHA y el origen real de la solicitud, aparecen errores de verificación del dominio. Estos fallos son silenciosos: el token parece válido pero el servidor lo rechaza. Esta guía cubre todos los escenarios de error relacionados con el dominio y cómo solucionarlos.


Cómo funciona la verificación de dominio

Site owner registers reCAPTCHA → adds allowed domains (example.com, www.example.com)
    ↓
reCAPTCHA widget loads on example.com → matches allowed domain ✓
    ↓
Token generated with embedded hostname
    ↓
Server validates token via siteverify API
    ↓
Google checks: Does token hostname match allowed domains?
    ├─ YES → { "success": true, "hostname": "example.com" }
    └─ NO  → { "success": false, error or hostname mismatch }

Donde se verifica el dominio

punto de control lo que se verifica
Lado del cliente El widget se carga solo en dominios permitidos (opcional, se puede deshabilitar)
Generación de tokens El nombre de host incrustado en el token coincide con el origen de la página
Validación del servidor siteverify devuelve el nombre de host; el servidor debe verificar que coincida

Errores comunes de verificación de dominio

Error 1: el nombre de host no coincide en la respuesta de siteverify

{
    "success": true,
    "hostname": "subdomain.example.com",
    "challenge_ts": "2025-01-15T10:30:00Z"
}

El token es válido, pero el campo hostname muestra un dominio diferente al esperado. Algunas implementaciones de servidor rechazan esto:

# Server-side validation that checks hostname
def validate_token(token, secret_key, expected_hostname):
    result = requests.post(
        "https://www.google.com/recaptcha/api/siteverify",
        data={"secret": secret_key, "response": token},
    ).json()

    if not result.get("success"):
        return False

    # This check causes failures when hostnames don't match
    if result.get("hostname") != expected_hostname:
        return False  # Domain mismatch!

    return True

Causas:

  • Token resuelto para www.example.com pero validado en example.com
  • Token resuelto para staging.example.com pero validado en example.com
  • Proxy o CDN cambia el nombre de host aparente

Solución: Asegúrese de que pageurl en su solicitud de solución coincida exactamente con el dominio donde se enviará el token.

Error 2: el widget se niega a cargarse

El widget reCAPTCHA muestra un error o no muestra:

ERROR: Invalid domain for site key

Causas:

  • Los dominios permitidos de la clave del sitio no incluyen el dominio de la página actual
  • Cargando el widget desde localhost o archivo: protocolo //
  • Usar una dirección IP en lugar de un nombre de dominio

Solución para la automatización: Este es un problema de configuración del propietario del sitio. Para resolverlo, asegúrese de pasar el pageurl correcto que coincida con un dominio permitido.

Error 3: token rechazado a pesar de la resolución correcta

{
    "success": false,
    "error-codes": ["invalid-input-response"]
}

El token se generó para un dominio diferente al que se está validando.

Causa común de automatización: El pageurl enviado al solucionador no coincide con el dominio de destino real:

# WRONG: pageurl doesn't match actual target
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": "https://staging.example.com/qa-login",  # ← Must match actual domain
    "json": 1,
})

# But submitting token to:
requests.post("https://app.staging.example.com/qa-login", ...)  # Different subdomain!

Reglas de coincidencia de dominios

Coincidencia exacta vs comodín

La verificación de dominio de reCAPTCHA no es una coincidencia estricta de subdominios de forma predeterminada. El comportamiento depende de la configuración del propietario del sitio:

Dominio registrado Orígenes aceptables
example.com example.com, www.example.com, sub.example.com (si el comodín está habilitado)
www.example.com Solo www.example.com (si es estricto)
*.example.com Cualquier subdominio de ejemplo.com
localhost Solo localhost (para desarrollo)

Comportamiento del nombre de host del lado del servidor

Al validar mediante siteverify, hostname en la respuesta refleja la página donde se generó el token. El servidor del propietario del sitio decide si lo acepta:

# Permissive validation (accepts any subdomain)
def validate_permissive(token, secret, base_domain):
    result = requests.post(
        "https://www.google.com/recaptcha/api/siteverify",
        data={"secret": secret, "response": token},
    ).json()

    if not result.get("success"):
        return False

    hostname = result.get("hostname", "")
    return hostname == base_domain or hostname.endswith(f".{base_domain}")


# Strict validation (exact match only)
def validate_strict(token, secret, expected_hostname):
    result = requests.post(
        "https://www.google.com/recaptcha/api/siteverify",
        data={"secret": secret, "response": token},
    ).json()

    return result.get("success") and result.get("hostname") == expected_hostname

Corregir errores de dominio en la automatización

Solución 1: haga coincidir exactamente la URL de la página

La solución más común es asegurarse de que pageurl coincida con el objetivo real:

# Correct: pageurl matches where you'll submit the token
target_url = "https://www.staging.example.com/qa-login"

submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": "6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
    "pageurl": target_url,  # Must match the actual domain
    "json": 1,
})

Solución 2: manejar www frente a no www

from urllib.parse import urlparse

def normalize_url(url):
    """Normalize URL for consistent domain matching."""
    parsed = urlparse(url)
    # Use exactly what the target site uses
    # Check if the site redirects www → non-www or vice versa
    return f"{parsed.scheme}://{parsed.netloc}{parsed.path}"

# Test which variant the site uses
response = requests.get("https://staging.example.com/qa-login", allow_redirects=True)
actual_url = response.url  # May be https://www.staging.example.com/qa-login after redirect

Solución 3: detectar el dominio correcto en la cadena de redireccionamiento

Algunos sitios redireccionan a través de múltiples dominios:

def get_final_url(url):
    """Follow redirects to find the actual CAPTCHA page domain."""
    response = requests.get(url, allow_redirects=True, timeout=15)
    return response.url

# Login URL might redirect:
# https://staging.example.com/qa-login → https://auth.staging.example.com/qa-login
final_url = get_final_url("https://staging.example.com/qa-login")
# Use final_url as pageurl for solver

Solución 4: extraiga el dominio de la URL de devolución de llamada de reCAPTCHA

from bs4 import BeautifulSoup
from urllib.parse import urlparse

def extract_recaptcha_domain(html, page_url):
    """Extract the domain reCAPTCHA uses for token binding."""
    soup = BeautifulSoup(html, "html.parser")

    # Check for reCAPTCHA iframe
    iframe = soup.find("iframe", src=lambda s: s and "recaptcha" in s)
    if iframe:
        src = iframe.get("src", "")
        # The iframe URL may contain the domain parameter
        if "domain=" in src:
            # Extract domain from iframe URL
            pass

    # Default: use the page URL's domain
    return urlparse(page_url).netloc

Herramienta de diagnóstico de verificación de dominio

import requests
from urllib.parse import urlparse

class DomainDiagnostic:
    """Diagnose domain verification issues for reCAPTCHA solving."""

    def __init__(self, target_url):
        self.target_url = target_url
        self.issues = []

    def check_redirects(self):
        """Check if the URL redirects to a different domain."""
        try:
            response = requests.get(
                self.target_url, allow_redirects=True, timeout=15,
                headers={"User-Agent": "Mozilla/5.0 Chrome/120.0.0.0"},
            )
            final_url = response.url
            original_domain = urlparse(self.target_url).netloc
            final_domain = urlparse(final_url).netloc

            if original_domain != final_domain:
                self.issues.append({
                    "type": "redirect",
                    "message": f"Redirects from {original_domain} to {final_domain}",
                    "fix": f"Use pageurl: {final_url}",
                })

            return final_url
        except Exception as e:
            self.issues.append({"type": "error", "message": str(e)})
            return self.target_url

    def check_www_variant(self):
        """Check if www and non-www point to the same content."""
        parsed = urlparse(self.target_url)
        domain = parsed.netloc

        if domain.startswith("www."):
            alt_domain = domain[4:]
        else:
            alt_domain = f"www.{domain}"

        alt_url = self.target_url.replace(domain, alt_domain)

        try:
            alt_response = requests.get(alt_url, allow_redirects=True, timeout=10)
            alt_final = urlparse(alt_response.url).netloc

            if alt_final != domain and alt_final != alt_domain:
                self.issues.append({
                    "type": "www_redirect",
                    "message": f"{alt_domain} redirects to {alt_final}",
                })
        except Exception:
            pass

    def report(self):
        """Generate diagnostic report."""
        final_url = self.check_redirects()
        self.check_www_variant()

        print(f"Target URL: {self.target_url}")
        print(f"Final URL:  {final_url}")
        print(f"Use as pageurl: {final_url}")

        if self.issues:
            print("\nIssues found:")
            for issue in self.issues:
                print(f"  [{issue['type']}] {issue['message']}")
                if "fix" in issue:
                    print(f"  Fix: {issue['fix']}")
        else:
            print("\nNo domain issues detected.")


# Usage
diag = DomainDiagnostic("https://staging.example.com/qa-login")
diag.report()

Tabla de solución de problemas

Síntoma causa probable Diagnóstico Solución
Token siempre rechazado pageurl no coincide con el dominio de destino Compare la URL de la página del solucionador con el dominio de envío real Actualizar URL de página para que coincida
Funciona en www, falla en sitios que no son www La variante del dominio no coincide Comprobar el comportamiento de redireccionamiento Utilice la variante que utiliza el sitio de destino (siga las redirecciones)
A veces funciona, a veces falla CDN o balanceador de carga sirve a diferentes dominios Compruebe si el dominio varía según la solicitud Utilice una URL coherente de la cadena de redireccionamiento
Funciona en el navegador, falla en el script Envíos de scripts desde diferente origen Compare la barra de URL del navegador con la URL de página del script Coincidir con la URL final del navegador
Token empresarial rechazado Enlace de proyecto o dominio incorrecto Verifique que la clave del sitio empresarial coincida con el dominio Verifique la configuración del dominio de la consola empresarial

Preguntas frecuentes

¿CaptchaAI maneja la verificación de dominio automáticamente?

CaptchaAI genera tokens vinculados al pageurl que usted proporciona. Debe asegurarse de que esta URL coincida con el dominio donde enviará el token. CaptchaAI no verifica la configuración del dominio: utiliza cualquier URL de página que especifique.

¿Puedo resolver un CAPTCHA para un dominio y usarlo en otro?

No. Los tokens reCAPTCHA están vinculados al dominio para el que se generaron. Un token generado para example.com no se puede utilizar en other-site.com. Incluso diferentes subdominios pueden fallar si el sitio valida estrictamente el nombre de host.

¿Por qué mi token funciona en pruebas pero falla en producción?

Causas comunes: (1) Las pruebas usan localhost que tiene reglas de dominio diferentes, (2) La producción usa una CDN con un dominio diferente, (3) La producción tiene una validación de nombre de host más estricta, (4) Ruta URL o cadena de redireccionamiento diferente en producción.

¿Importa el camino o sólo el dominio?

reCAPTCHA solo valida el dominio (nombre de host). La ruta (/login, /signup) no afecta la verificación del dominio. Sin embargo, aún debe usar la URL completa correcta como pageurl porque algunas implementaciones de solucionador pueden usarla para otros fines.


Resumen

La verificación del dominio reCAPTCHA vincula los tokens al nombre de host donde se generaron. El error de automatización más común es una discrepancia en pageurl: la URL pasada aCaptchaAIdebe coincidir con el dominio donde se enviará el token. Siga las redirecciones para encontrar el dominio real, maneje las variantes con www y sin www y use la herramienta de diagnóstico de dominio para identificar discrepancias antes de resolverlas.

Artículos relacionados

  • Cómo resolver la devolución de llamada de Recaptcha V2 usando Api
  • Torniquete Recaptcha V2 Manejo en el mismo sitio
  • Errores y correcciones comunes de Captcha de imágenes de cuadrícula
Los comentarios están deshabilitados para este artículo.