Comment résoudre un PopularCaptcha en Python (exemple fonctionnel, 2026)
Si votre script Python a rencontré un PopularCaptcha, vous n'avez pas besoin d'une ferme de navigateurs ni d'un modèle à vous. Il vous faut la sitekey de la page, une requête POST, et le jeton qui revient.
Ce guide vous mène de zéro à un jeton fonctionnel en cinq minutes environ : obtenir une clé API, trouver la sitekey, demander le jeton, le soumettre au formulaire, et gérer les cas d'échec qui apparaissent lorsqu'un script tourne sans surveillance. Les résolutions échouées sont gratuites, donc une nouvelle tentative ne coûte que du temps.
Scarnox résout PopularCaptcha aujourd'hui, avec ou sans votre propre proxy. Les autres types de captcha comme reCAPTCHA, Cloudflare Turnstile et AWS WAF arrivent bientôt, donc tous les exemples de ce guide utilisent PopularCaptcha. L'aperçu des types de captcha explique en quoi les autres diffèrent.
1. Obtenir une clé API
Créez un compte et commencez avec un crédit d'essai gratuit, sans carte bancaire. Votre clé API se trouve sur le tableau de bord. Gardez-la hors de votre code source et lisez-la depuis une variable d'environnement :
export SCARNOX_KEY="scarnox_YOURAPIKEY"
2. Trouver la sitekey
Ouvrez la page avec le captcha, ouvrez les outils de développement, et cherchez data-sitekey dans le panneau Éléments. Les sitekeys PopularCaptcha sont des UUID :
<div class="h-captcha" data-sitekey="10000000-ffff-ffff-ffff-000000000001"></div>
Pas de data-sitekey dans le HTML ? Le widget est probablement rendu par JavaScript. Regardez dans l'onglet Réseau la requête de configuration du widget ; son paramètre de requête sitekey est celui qu'il vous faut. D'autres moyens de la trouver couvrent l'URL de l'iframe et les widgets invisibles.
Envoyez comme site_url l'URL de la page qui affiche le widget. L'hôte compte le plus, mais l'URL complète de la page reste le choix sûr.
3. Demander un jeton
import os
import requests
API_URL = "https://api.scarnox.com/api/tasks/create"
API_KEY = os.environ["SCARNOX_KEY"]
def solve_captcha(sitekey: str, page_url: str) -> str:
r = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185, # l'appel bloque jusqu'à ce que le jeton soit prêt
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
if __name__ == "__main__":
token = solve_captcha("10000000-ffff-ffff-ffff-000000000001", "https://example.com/signup")
print(token[:40], "...")
C'est toute l'intégration. Il n'y a aucune boucle d'interrogation ni de second appel « obtenir le résultat ». La requête revient lorsque le jeton est prêt, donc le seul réglage qui compte est un délai suffisamment long pour couvrir une résolution lente. Utilisez environ 185 secondes.
Une réponse réussie a errorId à 0, avec le jeton sous solution.token. Tout autre errorId signifie que la résolution a échoué, et la réponse contient un errorCode et une errorDescription qui expliquent pourquoi.
4. Soumettre le jeton
Le jeton va là où le site attend la réponse au captcha. Pour PopularCaptcha, c'est presque toujours un champ de formulaire appelé h-captcha-response. Beaucoup de sites acceptent aussi g-recaptcha-response, envoyez donc les deux :
import requests
def sign_up(session: requests.Session, form_url: str, email: str, sitekey: str) -> requests.Response:
token = solve_captcha(sitekey, form_url)
return session.post(form_url, data={
"email": email,
"h-captcha-response": token,
"g-recaptcha-response": token,
}, timeout=30)
Deux détails comptent ici. Les vrais sites vérifient généralement les cookies de session de chargement de la page, donc chargez le formulaire avec le même requests.Session avant d'envoyer. Et envoyez vers l'URL action du formulaire, qui n'est pas toujours l'URL de la page.
Résolvez juste avant d'envoyer. Le jeton expire au bout d'environ deux minutes, donc ne le récupérez pas au début d'un long travail pour le garder. Si le site rejette le jeton, ouvrez le formulaire dans les outils de développement et vérifiez les noms des champs cachés.
5. Gérer les échecs
Les résolutions échouées sont gratuites, donc une nouvelle tentative ne coûte que du temps. Certaines erreurs ne réussiront jamais au nouvel essai, donc ne bouclez pas aveuglément. Vérifiez errorId à chaque fois, journalisez errorCode et errorDescription, et ne réessayez que les échecs passagers.
Les erreurs réseau demandent leur propre traitement, car requests lève une exception avant même qu'une réponse n'existe :
import requests
try:
token = solve_captcha(sitekey, page_url)
except requests.RequestException as exc:
print("network problem, retry later:", exc)
except RuntimeError as exc:
print("solve rejected:", exc)
Le guide de gestion des erreurs propose une politique de nouvelles tentatives complète, avec recul et gigue.
Erreurs courantes
- **Mauvaise
site_url.** Envoyez la page qui affiche le widget, pas la page d'accueil. - Jeton périmé. Un jeton utilisé après environ deux minutes est rejeté. Résolvez juste avant d'envoyer.
- Session absente. Un envoi sans les cookies de la page peut échouer même avec un jeton valide.
- **Certains sites exigent
rqdata.** Si la page fournit une valeurrqdatapour le widget, transmettez-la dans la requête comme champ facultatifrqdata. - Widget invisible. S'il n'y a pas de case à cocher et que le site démarre le widget depuis son propre code, ajoutez
"is_invisible": trueà la requête. Le guide sur le captcha invisible montre comment renvoyer le jeton.
Essayer gratuitement
Créez un compte et commencez avec un crédit d'essai gratuit, sans carte bancaire. Exécutez l'exemple ci-dessus sur un formulaire qui vous appartient avant de l'intégrer dans un travail plus large. Pour le coût de la résolution à grand volume, consultez les tarifs actuels.
Journaliser chaque résolution
Journalisez une ligne par résolution : la sitekey, l'hôte de la page, le errorId, le errorCode en cas d'échec, et la durée de l'appel. N'incluez ni la clé API ni le mot de passe d'un proxy. Ces lignes vous indiquent si une exécution lente l'est à cause de la page, du proxy ou du solveur. Ce sont aussi les premières informations dont vous aurez besoin si vous ouvrez une demande d'assistance.
Résoudre dans une boucle
Si votre script résout de nombreux captchas à la suite, gardez la boucle simple. Résolvez, envoyez, vérifiez le résultat, et seulement ensuite passez à la suite. Ne résolvez pas à l'avance pour mettre des jetons en file d'attente, car chacun expire au bout d'environ deux minutes. Une courte pause entre les résolutions sur un même site maintient votre rythme de requêtes proche de celui d'un humain.