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.compero validado enexample.com - Token resuelto para
staging.example.compero validado enexample.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