reCAPTCHA valide que les jetons sont utilisés sur le même domaine pour lequel ils ont été générés. Lorsqu'il y a une incompatibilité entre la configuration du domaine du CAPTCHA et l'origine réelle de la demande, vous obtenez des erreurs de vérification du domaine. Ces échecs sont silencieux : le jeton semble valide mais le serveur le rejette. Ce guide couvre tous les scénarios d'erreur liés au domaine et comment les corriger.
Comment fonctionne la vérification de domaine
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 }
Où le domaine est vérifié
| Point de contrôle | Ce qui est vérifié |
|---|---|
| Côté client | Le widget se charge uniquement sur les domaines autorisés (facultatif – peut être désactivé) |
| Génération de jetons | Le nom d'hôte intégré dans le jeton correspond à l'origine de la page |
| Validation du serveur | siteverify renvoie le nom d'hôte - le serveur doit vérifier qu'il correspond |
Erreurs courantes de vérification de domaine
Erreur 1 : incompatibilité de nom d'hôte dans la réponse de siteverify
{
"success": true,
"hostname": "subdomain.example.com",
"challenge_ts": "2025-01-15T10:30:00Z"
}
Le jeton est valide, mais le champ hostname affiche un domaine différent de celui attendu. Certaines implémentations de serveur rejettent cela :
# 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
Causes :
- Jeton résolu pour
www.example.commais validé surexample.com - Jeton résolu pour
staging.example.commais validé surexample.com - Le proxy ou le CDN modifie le nom d'hôte apparent
Correction : Assurez-vous que le pageurl dans votre demande de solveur correspond exactement au domaine dans lequel le jeton sera soumis.
Erreur 2 : le widget refuse de se charger
Le widget reCAPTCHA affiche une erreur ou ne s'affiche pas :
ERROR: Invalid domain for site key
Causes :
- Les domaines autorisés de la clé de site n'incluent pas le domaine de la page actuelle
- Chargement du widget depuis localhost ou file: Protocole //
- Utiliser une adresse IP au lieu d'un nom de domaine
Correction pour l'automatisation : Il s'agit d'un problème de configuration du propriétaire du site. Pour résoudre le problème, assurez-vous de transmettre le bon pageurl qui correspond à un domaine autorisé.
Erreur 3 : jeton rejeté malgré une résolution correcte
{
"success": false,
"error-codes": ["invalid-input-response"]
}
Le jeton a été généré pour un domaine différent de celui où il est en cours de validation.
Cause d'automatisation courante : Le pageurl envoyé au solveur ne correspond pas au domaine cible réel :
# 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://example.com/login", # ← Must match actual domain
"json": 1,
})
# But submitting token to:
requests.post("https://app.example.com/login", ...) # Different subdomain!
Règles de correspondance de domaine
Correspondance exacte vs caractère générique
La vérification de domaine de reCAPTCHA n'est pas une correspondance stricte de sous-domaine par défaut. Le comportement dépend de la configuration du propriétaire du site :
| Domaine enregistré | Origines acceptables |
|---|---|
example.com |
example.com, www.example.com, sub.example.com (si le caractère générique est activé) |
www.example.com |
www.example.com uniquement (si strict) |
*.example.com |
Tout sous-domaine de example.com |
localhost |
localhost uniquement (pour le développement) |
Comportement du nom d'hôte côté serveur
Lors de la validation via siteverify, le hostname dans la réponse reflète la page où le jeton a été généré. Le serveur du propriétaire du site décide s'il l'accepte :
# 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
Correction des erreurs de domaine dans l'automatisation
Correctif 1 : faire correspondre exactement l'URL de la page
La solution la plus courante : assurez-vous que pageurl correspond à la cible réelle :
# Correct: pageurl matches where you'll submit the token
target_url = "https://www.example.com/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,
})
Correctif 2 : gérer www et non-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://example.com/login", allow_redirects=True)
actual_url = response.url # May be https://www.example.com/login after redirect
Correctif 3 : Détecter le domaine correct à partir de la chaîne de redirection
Certains sites redirigent via plusieurs domaines :
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://example.com/login → https://auth.example.com/login
final_url = get_final_url("https://example.com/login")
# Use final_url as pageurl for solver
Correctif 4 : extraire le domaine de l'URL de rappel 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
Outil de diagnostic de vérification de domaine
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://example.com/login")
diag.report()
Tableau de dépannage
| Symptôme | Cause probable | Diagnostic | Corriger |
|---|---|---|---|
| Jeton toujours rejeté | l'URL de la page ne correspond pas au domaine cible | Comparez l'URL de la page du solveur avec le domaine de soumission réel | Mettre à jour l'URL de la page pour qu'elle corresponde |
| Fonctionne sur www, échoue sur non-www | Incompatibilité des variantes de domaine | Vérifier le comportement de redirection | Utilisez la variante utilisée par le site cible (suivre les redirections) |
| Fonctionne parfois, échoue parfois | CDN ou équilibreur de charge dessert différents domaines | Vérifiez si le domaine varie selon la demande | Utilisez une URL cohérente de la chaîne de redirection |
| Fonctionne dans le navigateur, échoue dans le script | Script envoyé depuis différentes origines | Comparez la barre d'URL du navigateur avec l'URL de la page du script | Faire correspondre l'URL finale du navigateur |
| Jeton d'entreprise rejeté | Mauvaise liaison de projet ou de domaine | Vérifier que la clé du site Enterprise correspond au domaine | Vérifier les paramètres de domaine de la console Enterprise |
Questions fréquemment posées
CaptchaAI gère-t-il automatiquement la vérification du domaine ?
CaptchaAI génère des jetons liés au pageurl que vous fournissez. Vous devez vous assurer que cette URL correspond au domaine dans lequel vous soumettez le jeton. CaptchaAI ne vérifie pas la configuration du domaine — il utilise l'URL de page que vous spécifiez.
Puis-je résoudre un CAPTCHA pour un domaine et l'utiliser sur un autre ?
Non. Les jetons reCAPTCHA sont liés au domaine pour lequel ils ont été générés. Un jeton généré pour example.com ne peut pas être utilisé sur other-site.com. Même des sous-domaines différents peuvent échouer si le site valide strictement le nom d'hôte.
Pourquoi mon jeton fonctionne-t-il en test mais échoue-t-il en production ?
Causes courantes : (1) Les tests utilisent localhost qui a des règles de domaine différentes, (2) La production utilise un CDN avec un domaine différent, (3) La production a une validation de nom d'hôte plus stricte, (4) Un chemin d'URL ou une chaîne de redirection différente en production.
Le chemin est-il important, ou seulement le domaine ?
Seul le domaine (nom d'hôte) est validé par reCAPTCHA. Le chemin (/login, /signup) n'affecte pas la vérification du domaine. Toutefois, vous devez toujours utiliser l'URL complète correcte sous la forme pageurl, car certaines implémentations de solveur peuvent l'utiliser à d'autres fins.
Résumé
La vérification du domaine reCAPTCHA associe les jetons au nom d'hôte où ils ont été générés. L'échec d'automatisation le plus courant est une incompatibilité pageurl : l'URL transmise àCaptchaAIdoit correspondre au domaine où le jeton sera soumis. Suivez les redirections pour trouver le domaine réel, gérez les variantes www et non-www et utilisez l'outil de diagnostic de domaine pour identifier les incohérences avant de les résoudre.
Articles connexes
- Comment résoudre le rappel Recaptcha V2 à l'aide de l'API
- Gestion du tourniquet Recaptcha V2 sur le même site
- Erreurs et correctifs courants de Captcha d’image de grille