Résolution de Problèmes

Erreurs et correctifs de vérification de domaine reCAPTCHA

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.com mais validé sur example.com
  • Jeton résolu pour staging.example.com mais validé sur example.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
Les commentaires sont désactivés pour cet article.