Pour automatiser la résolution d'un GeeTest v3, il faut d'abord récupérer trois paramètres directement sur la page cible — gt, challenge et api_server — avant même d'appeler l'API CaptchaAI. Contrairement à reCAPTCHA, où un simple sitekey suffit, GeeTest impose ce flux de vérification en deux temps : extraction, puis résolution. C'est cette étape d'extraction, souvent négligée, qui bloque la majorité des intégrations mal préparées.
Ce guide détaille l'extraction des paramètres GeeTest v3, puis la résolution du défi (glissière, icônes ou correspondance de mots) via l'API CaptchaAI, avec des exemples Python et Node.js réutilisables tels quels.
Ce que couvre ce guide :
- Récupérer
gt,challengeetapi_serverpar trois méthodes différentes - Envoyer la tâche à l'API CaptchaAI (
in.php) en Python et en Node.js - Interroger le résultat (
res.php) jusqu'à récupérer la solution - Transmettre
geetest_challenge,geetest_validateetgeetest_seccodeau site cible
Ce qu'il vous faut avant de commencer
Avant de commencer, réunissez les éléments suivants :
- Clé API CaptchaAI — depuis captchaai.com
- Valeur
gtde GeeTest — identifiant statique, propre à chaque site challengede GeeTest — valeur dynamique, générée à chaque session- URL de la page — l'URL où le GeeTest s'affiche
- Langage — Python 3.7+ ou Node.js 14+
Ce workflow fonctionne aussi bien en local que sur un pipeline CI hébergé sur OVHcloud ou Scaleway — seule la latence réseau change.
Étape 1 : récupérer les paramètres gt, challenge et api_server
GeeTest exige trois paramètres. Le gt est statique (identique à chaque requête), tandis que challenge change à chaque session — il faudra en récupérer un nouveau avant chaque résolution.
Méthode 1 — l'onglet Réseau de DevTools. C'est la plus fiable, quel que soit le site :
- Ouvrez l'onglet Réseau de DevTools
- Filtrez par
register-slide,gettype.phpouget.php - Déclenchez le CAPTCHA et repérez la requête d'initialisation
- La réponse contient
gt,challengeet parfoisapi_server
{
"success": 1,
"gt": "019924a82c70bb123aae90d483087f94",
"challenge": "12345678abc90def12345678abc90def",
"new_captcha": true
}
Méthode 2 — le code source de la page. Utile quand GeeTest est initialisé directement en JavaScript, sans requête réseau séparée :
// Search page source for initGeetest or gt value
document.querySelectorAll('script').forEach(s => {
if (s.textContent.includes('initGeetest')) {
console.log(s.textContent);
}
});
Méthode 3 — l'endpoint interne du site. De nombreux sites récupèrent eux-mêmes les paramètres GeeTest depuis leur propre API :
# The site's registration endpoint
params_response = requests.get("https://example.com/api/captcha/register")
data = params_response.json()
gt = data["gt"]
challenge = data["challenge"]
Astuce : commencez toujours par la Méthode 1 (onglet Réseau). Elle fonctionne sur la quasi-totalité des intégrations GeeTest v3 et évite de fouiller dans du JavaScript minifié pour retrouver
initGeetest.
Étape 2 : envoyer la tâche à l'API CaptchaAI
Une fois gt et challenge en main, transmettez-les à in.php avec method=geetest. En Python :
import requests
import time
API_KEY = "YOUR_API_KEY"
response = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "geetest",
"gt": "019924a82c70bb123aae90d483087f94",
"challenge": "12345678abc90def12345678abc90def",
"api_server": "api.geetest.com", # Optional, use if site specifies
"pageurl": "https://example.com/login",
"json": 1
})
data = response.json()
if data.get("status") != 1:
raise Exception(f"Submit error: {data.get('request')}")
task_id = data["request"]
print(f"Task submitted: {task_id}")
En Node.js, la même logique :
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
async function submitGeeTest(gt, challenge, pageurl) {
const { data } = await axios.get('https://ocr.captchaai.com/in.php', {
params: {
key: API_KEY,
method: 'geetest',
gt,
challenge,
api_server: 'api.geetest.com',
pageurl,
json: 1
}
});
if (data.status !== 1) throw new Error(`Submit error: ${data.request}`);
return data.request;
}
Étape 3 : interroger le résultat de la résolution
La résolution GeeTest renvoie trois valeurs (challenge, validate, seccode) — interrogez res.php toutes les 5 secondes jusqu'à les récupérer. En Python :
def get_geetest_solution(task_id):
for attempt in range(30):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1
}).json()
if result.get("status") == 1:
return result["request"]
if result.get("request") != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result.get('request')}")
raise Exception("Timeout")
solution = get_geetest_solution(task_id)
# solution = {
# "geetest_challenge": "12345678abc90def12345678abc90def1a",
# "geetest_validate": "abcdef1234567890abcdef1234567890",
# "geetest_seccode": "abcdef1234567890abcdef1234567890|jordan"
# }
En Node.js, le même mécanisme de polling :
async function getGeeTestSolution(taskId) {
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 5000));
const { data } = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: API_KEY, action: 'get', id: taskId, json: 1 }
});
if (data.status === 1) return data.request;
if (data.request !== 'CAPCHA_NOT_READY') throw new Error(data.request);
}
throw new Error('Timeout');
}
Étape 4 : transmettre la solution au site cible
Envoyez les trois valeurs à l'endpoint de vérification du site :
# Submit the GeeTest solution with the form data
verify_response = requests.post("https://example.com/api/login", data={
"username": "user@example.com",
"password": "password123",
"geetest_challenge": solution["geetest_challenge"],
"geetest_validate": solution["geetest_validate"],
"geetest_seccode": solution["geetest_seccode"]
})
print(f"Login status: {verify_response.status_code}")
Une fois la requête envoyée, vérifiez ces deux points avant de considérer le flux comme réussi :
- Le code HTTP retourné par le site (
200/302selon l'implémentation, jamais un rejet de type CAPTCHA) - L'absence de nouveau défi GeeTest sur la page suivante — un défi qui réapparaît signale une solution refusée
Exemple complet en Python
Voici l'ensemble du flux — extraction, envoi, interrogation, vérification — dans un seul script :
import requests
import time
API_KEY = "YOUR_API_KEY"
SITE_URL = "https://example.com/login"
# 1. Get GeeTest parameters from the site
params = requests.get("https://example.com/api/captcha/register").json()
# 2. Submit to CaptchaAI
submit = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "geetest",
"gt": params["gt"],
"challenge": params["challenge"],
"pageurl": SITE_URL,
"json": 1
}).json()
task_id = submit["request"]
# 3. Poll for solution
for _ in range(30):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1
}).json()
if result.get("status") == 1:
solution = result["request"]
break
# 4. Submit to site
login = requests.post(SITE_URL, data={
"username": "user@example.com",
"password": "pass",
"geetest_challenge": solution["geetest_challenge"],
"geetest_validate": solution["geetest_validate"],
"geetest_seccode": solution["geetest_seccode"]
})
print(f"Result: {login.status_code}")
Bonnes pratiques pour un workflow GeeTest v3 fiable
Quelques principes qui évitent la majorité des échecs en production :
- Récupérez toujours un
challengeneuf juste avant l'envoi à CaptchaAI plutôt que de le mettre en cache - Fixez un timeout raisonnable côté client (30 tentatives × 5 secondes suffisent dans la grande majorité des cas)
- Journalisez le
task_idretourné parin.phppour pouvoir corréler une résolution lente avec un ticket de support - Testez le flux complet sur votre environnement de staging avant de le pointer vers un site en production
- Surveillez le taux d'erreurs
ERROR_CAPTCHA_UNSOLVABLE: une hausse soudaine indique souvent que le site a changé son intégration GeeTest
Erreurs fréquentes et corrections
| Erreur | Cause | Correctif |
|---|---|---|
ERROR_BAD_PARAMETERS |
gt ou challenge manquant |
Les deux sont obligatoires : extrayez-les depuis la page |
ERROR_CAPTCHA_UNSOLVABLE |
Défi expiré ou invalide | Récupérez un défi neuf sur le site |
| Solution rejetée par le site | Valeur de challenge périmée |
Le défi est à usage unique : obtenez-en un nouveau à chaque tentative |
geetest_validate vide |
La résolution a échoué côté serveur | Réessayez avec un défi neuf |
L'exemple exécutable complet
Besoin d'un projet complet, avec configuration de l'environnement, interrogation du résultat, tentatives et gestion des erreurs ?
Consultez l'exemple exécutable complet sur GitHub →
FAQ
Comment automatiser l'extraction de gt et challenge avec Selenium ou Playwright ?
Interceptez la requête réseau vers register-slide (ou l'endpoint équivalent) grâce aux outils d'inspection réseau de Selenium ou Playwright, ou lisez directement le DOM si le site expose initGeetest dans le code source. Les méthodes 1 et 2 décrites plus haut s'automatisent sans difficulté particulière.
Que faire si la réponse de register-slide ne contient pas api_server ?
Rien de bloquant : ce paramètre est optionnel. Omettez-le dans la requête envoyée à CaptchaAI — la plupart des sites utilisent le serveur GeeTest par défaut, et l'API le détecte d'elle-même.
Combien de temps prend la résolution d'un GeeTest v3 via l'API CaptchaAI ?
Généralement entre 15 et 30 secondes, que ce soit pour un puzzle de glissière ou un défi d'icônes ; les temps de résolution sont comparables entre les types de défis.
CaptchaAI prend-il en charge GeeTest v4 ?
Non — pas encore. GeeTest v4 repose sur un protocole différent de GeeTest v3, et son support est seulement à venir. Vérifiez toujours la version exacte de GeeTest utilisée par le site avant d'implémenter ce workflow.
Peut-on valider ce workflow sur un environnement de staging avant la mise en production ?
Oui, et c'est même recommandé. Testez l'extraction des paramètres et la résolution sur votre propre environnement, avec vos identifiants de test, avant de déployer le flux contre un site en production.