La cause de ERROR_PAGEURL est presque toujours la même : le paramètre pageurl que vous envoyez à l'API ne pointe pas exactement vers la page où le CAPTCHA s'affiche. Le service valide le token par rapport au domaine d'origine, donc une URL approximative suffit à faire échouer la résolution, même quand le reste de votre requête est parfaitement correct.
La bonne nouvelle : la correction est mécanique. Une fois que vous savez d'où vient l'écart, quelques lignes de Python suffisent à normaliser l'URL avant chaque envoi.
Ce que le pageurl doit reproduire exactement
Un token de CAPTCHA n'est pas une valeur universelle : il est rattaché au domaine qui a servi le défi. Le champ pageurl sert à indiquer ce domaine d'origine, et trois éléments doivent correspondre au caractère près à ce que le navigateur affiche :
- Le protocole :
https(rarementhttp), jamais une URL nue sans schéma. - Le domaine complet :
www.example.cometexample.comsont deux hôtes distincts. - Le chemin visible : celui de la barre d'adresse, pas l'endpoint d'API vers lequel le formulaire poste.
Le principe est identique pour reCAPTCHA v2, reCAPTCHA v3 et Cloudflare Turnstile : l'URL doit refléter la page réelle au moment où le CAPTCHA apparaît.
Diagnostic en trois vérifications
Avant de plonger dans le code, ce parcours résout la grande majorité des cas :
- Comparez votre
pageurlà ce que montre la barre d'adresse une fois le CAPTCHA visible. - Vérifiez qu'aucune redirection ne change l'URL entre votre appel et l'affichage.
- Confirmez que le CAPTCHA n'est pas rendu dans une iframe ou une route SPA qui masque la vraie page.
Les sections suivantes détaillent chacun de ces points, avec l'utilitaire Python à réutiliser.
Récupérer la bonne URL depuis le navigateur
Règle : copiez l'URL affichée dans la barre d'adresse au moment où le CAPTCHA est visible.
# WRONG — incomplete URL
pageurl = "example.com/login"
# WRONG — wrong protocol
pageurl = "http://example.com/login"
# CORRECT — full URL with protocol
pageurl = "https://example.com/login"
# CORRECT — with www if that's what the page uses
pageurl = "https://www.example.com/login"
Astuce rapide : ouvrez la console du navigateur sur la page concernée et lisez window.location.href. Vous obtenez l'URL exacte, protocole et sous-domaine compris, sans risque de la retaper à la main.
Valider le pageurl avant chaque envoi
Plutôt que de déboguer après coup, filtrez l'URL en amont. Ce petit utilitaire refuse les URL sans protocole, retire le fragment #... que le serveur ne reçoit jamais, et conserve les paramètres de requête utiles.
from urllib.parse import urlparse
def validate_pageurl(url):
"""Validate pageurl before API submission."""
parsed = urlparse(url)
if not parsed.scheme:
raise ValueError(f"Missing protocol: {url}. Use https://")
if parsed.scheme not in ("http", "https"):
raise ValueError(f"Invalid protocol: {parsed.scheme}")
if not parsed.netloc:
raise ValueError(f"Missing domain: {url}")
# Remove fragment (hash) — not sent to server
clean = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
if parsed.query:
clean += f"?{parsed.query}"
return clean
# Usage
url = validate_pageurl("https://example.com/login#section")
# Returns: "https://example.com/login"
Concrètement, cette fonction :
- rejette toute URL sans schéma
http/httpsavec un message explicite ; - supprime le fragment
#..., qui n'est jamais transmis au serveur ; - préserve la chaîne de requête utile au rendu de la page.
Suivre les redirections pour éviter ERROR_PAGEURL
C'est le piège le plus courant : la page fonctionne dans le navigateur mais échoue dans le code parce qu'une redirection change l'URL avant l'affichage du CAPTCHA. Suivez-la explicitement et servez-vous de l'URL finale.
import requests
def get_final_url(url):
"""Follow redirects to get the actual page URL."""
resp = requests.get(url, allow_redirects=True, timeout=15)
return resp.url
# If the login page redirects
original = "https://example.com/login"
final = get_final_url(original)
print(f"Final URL: {final}")
# Use final URL as pageurl
Exemple concret : www contre non-www en production
Un cas typique rencontré par les équipes francophones : une boutique héberge son back-office sur example.com, mais l'équipe marketing a mis en place une redirection permanente vers www.example.com pour le référencement. Votre worker, déployé par exemple sur une instance OVHcloud à Gravelines ou dans la région AWS eu-west-3 (Paris), envoie https://example.com/login comme pageurl. Le navigateur, lui, affiche https://www.example.com/login après la redirection. Le token est bien résolu, mais le site le rejette parce que le domaine ne correspond pas. Un simple appel à get_final_url() avant l'envoi aligne les deux et fait disparaître l'erreur.
Gérer les applications monopages (SPA)
Les SPA modifient l'URL via JavaScript, sans rechargement complet de la page. Ce qui compte, c'est le domaine sur lequel le CAPTCHA est réellement rendu, pas l'endpoint d'API vers lequel le formulaire poste ses données.
# For SPAs, use the domain root + the route shown in the address bar
# NOT the API endpoint that the form submits to
# WRONG — API endpoint
pageurl = "https://api.example.com/v1/auth/login"
# CORRECT — the page URL shown in browser
pageurl = "https://example.com/login"
CAPTCHA chargés dans une iframe
Quand un CAPTCHA s'affiche dans une iframe servie par un autre domaine, gardez l'URL de la page principale. Le src de l'iframe n'est pas le bon pageurl.
# If the CAPTCHA is on the MAIN page
pageurl = "https://example.com/register" # Main page URL
# If the CAPTCHA is in an IFRAME with a different domain
# Still use the main page URL, not the iframe src
pageurl = "https://example.com/register"
# NOT: "https://captcha-frame.example.com/challenge"
Envoyer une requête correcte à l'API
En pratique, validez d'abord l'URL, puis soumettez la tâche. Le champ pageurl normalisé accompagne votre clé et le sitekey de la page.
import requests
# Validate URL first
pageurl = validate_pageurl("https://example.com/login")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "SITE_KEY",
"pageurl": pageurl,
"json": 1,
})
result = resp.json()
if result.get("status") == 1:
print(f"Task ID: {result['request']}")
else:
print(f"Error: {result.get('request')}")
Les causes d'incompatibilité, récapitulées
Si l'erreur persiste malgré la validation, ce tableau relie chaque cause à son exemple typique :
| Cause | Exemple |
|---|---|
| Protocole manquant | example.com au lieu de https://example.com |
| Domaine incorrect | www.example.com au lieu de example.com |
| Redirection qui modifie l'URL | Un formulaire sur /login redirigé vers /auth/login |
| Route SPA différente de l'URL serveur | La route JS /app/login ne correspond pas à l'URL réelle |
| Encodage d'URL défaillant | Espaces ou caractères spéciaux non encodés |
| Iframe hébergée sur un autre domaine | CAPTCHA chargé depuis un sous-domaine |
Tableau de dépannage rapide
| Symptôme | Cause probable | Correctif |
|---|---|---|
| L'URL semble correcte mais l'erreur persiste | Écart entre www et non-www |
Recopiez la barre d'adresse au caractère près |
| L'URL fonctionne par intermittence | Variantes d'URL liées aux tests A/B | Capturez l'URL au moment exact de la résolution |
| Token résolu mais refusé par le site | Le domaine du token ne correspond pas à celui du site | Alignez le domaine du pageurl sur celui du site |
| Fonctionne dans le navigateur, échoue dans le code | Redirection non suivie par le script | Passez par get_final_url() |
| L'URL contient des paramètres de requête | Certains paramètres sont nécessaires au rendu | Conservez les paramètres utiles à la page |
FAQ
Comment récupérer le bon pageurl en une seule ligne ?
Ouvrez la console du navigateur sur la page où le CAPTCHA apparaît et lisez window.location.href. Vous obtenez l'URL exacte, avec le protocole et le sous-domaine, sans risque d'erreur de saisie.
ERROR_PAGEURL concerne-t-il aussi Cloudflare Turnstile et reCAPTCHA v3 ?
Oui. La règle est identique pour reCAPTCHA v2, reCAPTCHA v3 et Cloudflare Turnstile : le pageurl doit correspondre à la page visible qui charge le défi, quel que soit le type de CAPTCHA.
Faut-il conserver le fragment #section dans le pageurl ?
Non. Le fragment après # n'est jamais transmis au serveur et n'entre pas dans la validation. La fonction validate_pageurl() le retire pour vous, ce qui évite les faux écarts.
Le pageurl doit-il obligatoirement être en HTTPS ?
Utilisez exactement le schéma affiché par la page, ce qui est presque toujours https. Envoyer http alors que la page est servie en https (ou l'inverse) crée une incompatibilité de domaine d'origine.
Guides connexes
Envoyez le bon pageurl du premier coup — testez la résolution avec CaptchaAI.