Neuf échecs GeeTest v3 sur dix se ramènent à une seule cause : une valeur challenge périmée. Avant de suspecter votre clé API, votre pageurl ou votre code de soumission, vérifiez ce point en premier — c'est le correctif le plus rapide et le plus fréquent.
La documentation de l'API GeeTest v3 de CaptchaAI est sans ambiguïté : vous devez obtenir une nouvelle valeur challenge pour chaque requête de résolution. Dès que le widget se charge sur la page, l'ancien défi devient invalide. Une intégration peut donc échouer alors même que la requête semble parfaitement formée. Contrairement à reCAPTCHA v2, qui renvoie un unique token, GeeTest v3 repose sur ce paramètre dynamique et renvoie trois valeurs à replacer sur la page.
Le reste des pannes se répartit en trois moments distincts :
- la soumission à l'API (
in.php) — la tâche est refusée avant même d'être mise en file ; - l'interrogation du résultat (
res.php) — la tâche part, mais le polling renvoie une erreur ; - la validation côté page cible — l'API renvoie des valeurs, mais le formulaire les refuse malgré tout.
Ce guide passe en revue chaque famille d'échec et donne, pour chacune, le correctif le plus direct.
Le coupable numéro un : un challenge périmé
S'il n'y a qu'une chose à contrôler avant tout, c'est la fraîcheur du challenge.
GeeTest v3 s'appuie sur deux paramètres essentiels :
gt— la clé publique du site (statique, elle ne change pas)challenge— la clé de défi dynamique (elle change à chaque chargement de page)
Pourquoi la résolution casse
La valeur challenge est générée à l'initialisation du widget GeeTest sur la page. Si vous la capturez une fois puis la réutilisez sur plusieurs requêtes de résolution, chaque requête après la première va, au choix :
- être rejetée par l'API dès la soumission, ou
- produire un résultat que la page cible refuse, parce que le défi a expiré
Comment le corriger
Avant chaque requête de résolution, procédez dans cet ordre :
- inspectez les appels réseau de la page pour repérer celui qui renvoie un
challengeneuf ; - rejouez cet appel pour obtenir une valeur fraîche ;
- envoyez-la immédiatement à CaptchaAI, sans la mettre en cache.
# Pseudocode: fetch a fresh challenge before each solve
import requests
def get_fresh_challenge(target_url):
"""Hit the GeeTest init endpoint to get a new challenge."""
resp = requests.get(f"{target_url}/geetest/register", timeout=10)
data = resp.json()
return data["challenge"], data["gt"]
challenge, gt = get_fresh_challenge("https://example.com")
# Now submit to CaptchaAI immediately — do not delay
Règle empirique : si plus de quelques secondes s'écoulent entre la capture du
challengeet l'envoi de la requête de résolution, récupérez-en un nouveau.
Par où commencer : l'ordre de diagnostic
Si votre intégration GeeTest échoue, remontez la chaîne dans cet ordre, du correctif le plus fréquent au plus rare :
- Le défi d'abord — est-il récent ? Récupérez-en un nouveau juste avant chaque résolution.
- Les paramètres ensuite —
gt,challengeetpageurldoivent tous être corrects. - Le mappage des champs — les
challenge,validateetseccoderenvoyés doivent atterrir dans les bons champs. - La comparaison finale — capturez avec les DevTools la structure exacte d'une résolution manuelle réussie et alignez-vous dessus.
Erreurs à la soumission (in.php)
Ces échecs surviennent quand vous envoyez la tâche à https://ocr.captchaai.com/in.php.
ERROR_WRONG_USER_KEY
- Cause : le format de la clé API est incorrect (elle doit compter 32 caractères).
- Correctif : vérifiez la clé depuis captchaai.com/api.php. N'ajoutez ni caractères ni espaces superflus.
ERROR_KEY_DOES_NOT_EXIST
- Cause : la clé API est bien formée, mais ne correspond à aucun compte actif.
- Correctif : connectez-vous à votre tableau de bord CaptchaAI et confirmez que la clé est active.
ERROR_ZERO_BALANCE
- Cause : aucun thread libre sur votre forfait actuel. Le plus petit forfait, BASIC ($15/mois, 5 threads), vous laisse cinq résolutions simultanées.
- Correctif : attendez qu'un thread se libère, réduisez la simultanéité, ou passez à un forfait supérieur.
ERROR_PAGEURL
- Cause : le paramètre
pageurlest absent de la requête. - Correctif : ajoutez l'URL complète de la page où le widget GeeTest se charge. Exemple :
pageurl=https://example.com/login
ERROR_BAD_PARAMETERS
Cause : un ou plusieurs champs obligatoires sont manquants ou mal formés. Pour GeeTest, les paramètres requis sont les suivants :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
key |
Chaîne | Oui | Votre clé API CaptchaAI |
method |
Chaîne | Oui | Doit valoir geetest |
gt |
Chaîne | Oui | Clé publique statique du site |
challenge |
Chaîne | Oui | Clé de défi dynamique (doit être fraîche) |
pageurl |
Chaîne | Oui | URL complète de la page |
Correctif : assurez-vous que gt, challenge et pageurl sont tous présents et correctement formatés.
Réponses HTML ou 500/502
- Cause : erreur transitoire côté serveur — ce n'est pas un problème de paramètre.
- Correctif : patientez 5 à 10 secondes, puis relancez la requête.
Erreurs à l'interrogation du résultat (res.php)
Ces échecs surviennent quand vous interrogez https://ocr.captchaai.com/res.php.
CAPCHA_NOT_READY
Ce n'est pas une erreur. Cela signifie que la résolution est encore en cours. Sur CaptchaAI, une résolution GeeTest v3 aboutit généralement en moins de 12 secondes, avec un taux de réussite élevé.
Correctif : attendez 5 secondes et interrogez de nouveau. Ne comptez pas cette réponse comme un échec.
ERROR_WRONG_ID_FORMAT
- Cause : le format de l'ID de captcha est incorrect — les identifiants sont exclusivement numériques.
- Correctif : vérifiez que vous utilisez l'ID exact renvoyé par
in.php, sans le modifier.
ERROR_WRONG_CAPTCHA_ID
- Cause : l'ID ne correspond à aucune tâche soumise.
- Correctif : contrôlez l'identifiant renvoyé dans la réponse de soumission. Si vous avez envoyé plusieurs tâches, veillez à interroger la bonne.
ERROR_EMPTY_ACTION
- Cause : le paramètre
actionest manquant ou vide dans votre requête d'interrogation. - Correctif : incluez
action=getdans chaque requête d'interrogation :
https://ocr.captchaai.com/res.php?key=YOUR_KEY&action=get&id=CAPTCHA_ID
ERROR_CAPTCHA_UNSOLVABLE
- Cause : le défi n'a pas pu être résolu — souvent à cause d'une valeur
challengepérimée ou d'une variante GeeTest non prise en charge. - Correctif : récupérez un
challengefrais et réessayez.
ERROR_INTERNAL_SERVER_ERROR
- Cause : incident côté serveur chez CaptchaAI.
- Correctif : patientez 10 secondes et réessayez.
Quand l'API réussit mais que la page cible refuse
Ce sont les pannes les plus délicates à déboguer : l'API CaptchaAI renvoie un résultat valide, mais la page cible le rejette malgré tout.
Prenez le cas d'une équipe QA qui valide un portail interne hébergé sur Scaleway (région Paris) : la requête part, le résultat arrive, et pourtant le formulaire reste bloqué. Neuf fois sur dix, le problème n'est pas la résolution elle-même, mais la façon dont les valeurs sont réinjectées.
Quand une résolution GeeTest v3 aboutit, l'API renvoie trois valeurs :
{
"challenge": "1a2b3456cd67890e12345fab678901c2de",
"validate": "09fe8d7c6ba54f32e1dcb0a9fedc8765",
"seccode": "12fe3d4c56789ba01f2e345d6789c012|jordan"
}
Elles doivent être renvoyées à la page cible ainsi :
| Champ de la réponse API | Champ attendu par la page |
|---|---|
challenge |
geetest_challenge |
validate |
geetest_validate |
seccode |
geetest_seccode |
Cause 1 : mappage de champs erroné
- Symptôme : l'API renvoie des valeurs, mais la page les rejette aussitôt.
- Cause : les valeurs sont insérées dans les mauvais champs ou dans le mauvais chemin de requête.
- Correctif : inspectez le trafic réseau d'une résolution manuelle de GeeTest sur la page cible. Repérez la requête POST qui envoie le résultat GeeTest et faites correspondre vos noms de champs à l'identique.
Cause 2 : challenge périmé récupéré en amont
- Symptôme : l'API renvoie des valeurs, mais la page annonce un défi expiré ou invalide.
- Cause : la valeur
challengea été capturée trop tôt, ou réutilisée. - Correctif : récupérez un
challengeneuf juste avant chaque requête de résolution. Ne le mettez pas en cache, ne le réutilisez pas.
Cause 3 : mauvais contexte de page
- Symptôme : la validation échoue même avec des entrées fraîches.
- Cause : le
pageurltransmis à CaptchaAI ne correspond pas à la page réelle sur laquelle le widget GeeTest a été chargé. - Correctif : utilisez l'URL exacte, protocole et chemin compris. Si le widget est chargé en AJAX sur une autre route, indiquez l'URL de cette route.
Cause 4 : structure de requête inadaptée
- Symptôme : les champs sont bons, mais le format de la requête est incorrect.
- Cause : la page cible attend les champs GeeTest dans un type de contenu précis (corps JSON ou données de formulaire, par exemple), ou aux côtés d'autres champs de formulaire.
- Correctif : comparez votre requête de soumission au trafic d'une résolution manuelle. Alignez le type de contenu, l'ordre des champs et tout champ supplémentaire. Pendant cette capture réseau, restez sobre sur les données : ne conservez que le trafic utile au diagnostic, sans données personnelles — un réflexe RGPD qui simplifie aussi la lecture des logs.
De l'erreur au correctif : tableau de référence
| Erreur / symptôme | Étape | Cause probable | Correctif |
|---|---|---|---|
ERROR_WRONG_USER_KEY |
Soumission | Clé API mal formée | Vérifier la clé de 32 caractères |
ERROR_KEY_DOES_NOT_EXIST |
Soumission | Clé invalide | Contrôler le tableau de bord |
ERROR_ZERO_BALANCE |
Soumission | Aucun thread libre | Attendre ou monter en forfait |
ERROR_PAGEURL |
Soumission | pageurl manquant |
Ajouter l'URL complète de la page |
ERROR_BAD_PARAMETERS |
Soumission | gt, challenge ou pageurl manquant |
Vérifier tous les champs requis |
CAPCHA_NOT_READY |
Interrogation | Résolution en cours | Attendre 5 secondes, réessayer |
ERROR_WRONG_ID_FORMAT |
Interrogation | ID de captcha non numérique | Utiliser l'ID exact de in.php |
ERROR_WRONG_CAPTCHA_ID |
Interrogation | ID de captcha invalide | Contrôler l'ID de soumission |
ERROR_EMPTY_ACTION |
Interrogation | action=get manquant |
Ajouter le paramètre action |
ERROR_CAPTCHA_UNSOLVABLE |
Interrogation | Défi périmé ou variante non prise en charge | Rafraîchir le défi, réessayer |
| L'API renvoie des valeurs, la page refuse | Validation | Défi périmé, champs erronés, mauvaise URL | Rafraîchir le défi, vérifier le mappage |
Python : résolution GeeTest v3 complète avec challenge neuf
import time
import requests
API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def get_fresh_challenge(target_url):
"""Fetch a fresh GeeTest challenge from the target page."""
resp = requests.get(f"{target_url}/api/geetest/register", timeout=10)
data = resp.json()
return data["gt"], data["challenge"]
def solve_geetest_v3(api_key, gt, challenge, pageurl):
"""Submit a GeeTest v3 challenge and return the validation package."""
# Submit
submit_resp = requests.post(
SUBMIT_URL,
data={
"key": api_key,
"method": "geetest",
"gt": gt,
"challenge": challenge,
"pageurl": pageurl,
"json": 1,
},
timeout=30,
)
submit_resp.raise_for_status()
submit_data = submit_resp.json()
if submit_data.get("status") != 1:
raise RuntimeError(f"Submit failed: {submit_data}")
captcha_id = submit_data["request"]
print(f"Task created — captcha ID: {captcha_id}")
# Wait before first poll
time.sleep(15)
# Poll for result
for _ in range(60):
result_resp = requests.get(
RESULT_URL,
params={
"key": api_key,
"action": "get",
"id": captcha_id,
"json": 1,
},
timeout=30,
)
result_resp.raise_for_status()
result_data = result_resp.json()
if result_data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result_data.get("status") == 1:
return result_data["request"]
raise RuntimeError(f"Polling error: {result_data}")
raise TimeoutError("GeeTest v3 solve timed out")
# Usage: always fetch a fresh challenge first
PAGE_URL = "https://example.com/login"
gt, challenge = get_fresh_challenge(PAGE_URL)
result = solve_geetest_v3(API_KEY, gt, challenge, PAGE_URL)
print(f"Result: {result}")
# The result contains: challenge, validate, seccode
# Map them to: geetest_challenge, geetest_validate, geetest_seccode
Node.js : résolution GeeTest v3 complète avec challenge neuf
const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function getFreshChallenge(targetUrl) {
const resp = await fetch(`${targetUrl}/api/geetest/register`);
const data = await resp.json();
return { gt: data.gt, challenge: data.challenge };
}
async function solveGeetestV3(apiKey, gt, challenge, pageurl) {
// Submit
const submitResp = await fetch(SUBMIT_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
key: apiKey,
method: "geetest",
gt: gt,
challenge: challenge,
pageurl: pageurl,
json: "1",
}),
});
const submitData = await submitResp.json();
if (submitData.status !== 1) {
throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
}
const captchaId = submitData.request;
console.log(`Task created — captcha ID: ${captchaId}`);
await sleep(15_000);
// Poll for result
for (let i = 0; i < 60; i++) {
const resultResp = await fetch(
`${RESULT_URL}?${new URLSearchParams({
key: apiKey,
action: "get",
id: captchaId,
json: "1",
})}`
);
const resultData = await resultResp.json();
if (resultData.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (resultData.status === 1) {
return resultData.request;
}
throw new Error(`Polling error: ${JSON.stringify(resultData)}`);
}
throw new Error("GeeTest v3 solve timed out");
}
// Usage
const PAGE_URL = "https://example.com/login";
(async () => {
const { gt, challenge } = await getFreshChallenge(PAGE_URL);
const result = await solveGeetestV3(API_KEY, gt, challenge, PAGE_URL);
console.log("Result:", result);
// Map result fields to: geetest_challenge, geetest_validate, geetest_seccode
})();
FAQ
Comment récupérer un challenge neuf avant chaque résolution ?
Rejouez l'appel réseau qui initialise le widget GeeTest sur la page (souvent un endpoint de type register), lisez la valeur challenge retournée, puis envoyez-la à CaptchaAI dans la foulée. L'idée est de ne jamais mettre cette valeur en cache : un challenge capturé pour une session ne vaut que pour cette session.
Combien de temps prend une résolution GeeTest v3 avec CaptchaAI ?
Généralement moins de 12 secondes, avec un taux de réussite élevé sur ce type. Tant que l'API répond CAPCHA_NOT_READY, la résolution est en cours : attendez 5 secondes et interrogez res.php de nouveau plutôt que de relancer une nouvelle tâche.
Pourquoi la page cible refuse-t-elle un résultat pourtant valide ?
Presque toujours pour l'une de ces trois raisons :
- le
challengea été récupéré trop tôt et a déjà expiré au moment de la soumission ; - les champs
geetest_challenge/geetest_validate/geetest_seccodesont mal mappés ; - le
pageurltransmis ne correspond pas à la route réelle où le widget se charge.
Comparez votre requête d'envoi au trafic d'une résolution manuelle pour trancher.
Que signifie l'erreur ERROR_CAPTCHA_UNSOLVABLE en GeeTest ?
Que le défi n'a pas pu être résolu, le plus souvent parce que la valeur challenge était déjà expirée à la soumission, ou parce qu'il s'agit d'une variante GeeTest non prise en charge. Récupérez un défi frais et renvoyez la tâche avant de conclure à un problème plus profond.
CaptchaAI prend-il en charge GeeTest v4 ?
Non — GeeTest v4 n'est pas encore pris en charge ; il est annoncé comme « à venir ». Cet article ne couvre que GeeTest v3. Pour la liste à jour des types résolus, consultez la documentation de l'API CaptchaAI.
Réparer votre intégration GeeTest
Commencez par le solveur GeeTest v3 de CaptchaAI, confirmez vos paramètres via la documentation de l'API, et consultez le fonctionnement du CAPTCHA GeeTest v3 s'il vous manque le déroulé du défi.
Journal d'itération
| Itération | Axe | Changements |
|---|---|---|
| Brouillon 1 | Structure et contenu | Ébauche de dépannage : 3 étapes d'erreur, tableau erreur-correctif, FAQ |
| Brouillon 2 | Exactitude technique | Codes d'erreur et paramètres GeeTest vérifiés contre captchaai.com/api-docs. Ajout du tableau des paramètres API. Mappage challenge/validate/seccode confirmé. |
| Brouillon 3 | Exemples de code | Ajout d'exemples complets Python et Node.js avec récupération d'un défi frais. Ajout du pseudocode du motif de rafraîchissement. |
| Brouillon 4 | Profondeur des échecs de validation | Section page cible étendue à 4 modes d'échec distincts. Ajout du tableau de mappage. Ajout du diagnostic de structure de requête. |
| Brouillon 5 | Polissage QA final | Codes d'erreur alignés sur les docs officiels. Ajout du tableau de référence. Introduction resserrée. Liens de cluster ajoutés. Réponses FAQ prêtes pour le balisage schema. |
Brief des visuels
Image de héros
- Texte alternatif : développeur en train de déboguer des erreurs GeeTest v3 — diagnostic des échecs de soumission, d'interrogation et de validation
- Doit montrer : un contexte de débogage avec les étapes du flux d'erreurs et les points de défaillance
- Nom de fichier : geetest-v3-errors-troubleshooting-hero.png
Visuel 1 dans l'article
- Emplacement : après « Erreurs à l'interrogation du résultat »
- Type : arbre de décision
- Texte alternatif : arbre de décision des échecs GeeTest v3 — erreurs de soumission, d'interrogation et de validation
- Nom de fichier : geetest-v3-error-decision-tree.png
Visuel 2 dans l'article
- Emplacement : après « Quand l'API réussit mais que la page cible refuse »
- Type : schéma causes et correctifs
- Texte alternatif : schéma des causes courantes de rejet d'une page GeeTest v3 et de leurs correctifs
- Nom de fichier : geetest-v3-validation-causes-fixes.png