GeeTest v3 не работает как reCAPTCHA: капча не решается «вслепую» — сайт отдаёт три параметра, gt, challenge и api_server, и без них запрос в CaptchaAI просто не пройдёт. gt статичен для сайта, challenge меняется на каждой сессии, а сама задача может быть слайдом, кликом по значкам или сопоставлением слов — на API это не влияет: параметры и порядок действий одинаковы для всех трёх.
Если прогоняете сценарий на форме логина или чекауте с настоящими пользовательскими данными, используйте staging-окружение и собирайте только те данные, которые вправе обрабатывать. Для аудитории в РФ это прямо требует 152-ФЗ «О персональных данных», для остальных стран действует аналогичная должная осмотрительность в духе GDPR — фиксируйте это на уровне процесса, а не по памяти.
Ниже — весь путь от извлечения параметров до передачи готового решения на целевой сайт, с кодом на Python и Node.js, который вставляется в проект без правок логики. Понадобится API-ключ CaptchaAI (получить на captchaai.com), сама пара gt/challenge со страницы и Python 3.7+ либо Node.js 14+.
Почему GeeTest нельзя решить «в лоб»
gt— статический идентификатор виджета на сайте, повторяется в каждом запросе.challenge— динамическое значение, выдаётся заново на каждую сессию и одноразовое: как только по нему что-то решили или истёк срок, сайт его больше не примет.api_server— опциональный параметр; указывайте, если сайт явно ссылается на нестандартный сервер GeeTest (api.geetest.comилиapi-na.geetest.com).- Без всех трёх значений CaptchaAI не сможет даже принять задачу — сначала параметры извлекаются со страницы, и только потом идёт запрос к API.
Шаг 1: извлеките gt и challenge со страницы
gt одинаков для каждого запроса к сайту, challenge — одноразовый и выдаётся заново на каждую сессию. Есть три рабочих способа его получить, от самого надёжного к запасному.
Способ 1 — вкладка Network в DevTools (самый надёжный):
- Откройте DevTools → вкладку Network.
- Отфильтруйте запросы по
register-slide,gettype.phpилиget.php. - Запустите капчу и найдите запрос инициализации.
- В ответе будут
gt,challengeи иногдаapi_server.
{
"success": 1,
"gt": "019924a82c70bb123aae90d483087f94",
"challenge": "12345678abc90def12345678abc90def",
"new_captcha": true
}
Способ 2 — исходный код страницы, если запрос инициализации не пойман или заблокирован блокировщиком:
// Search page source for initGeetest or gt value
document.querySelectorAll('script').forEach(s => {
if (s.textContent.includes('initGeetest')) {
console.log(s.textContent);
}
});
Способ 3 — собственный API сайта. Часть сайтов отдают параметры GeeTest отдельным запросом ещё до отрисовки виджета:
# 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"]
Шаг 2: отправьте задачу в CaptchaAI
На Python запрос собирается через requests:
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://staging.example.com/qa-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}")
На Node.js — тот же запрос через axios:
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;
}
Шаг 3: опросите res.php за решением
Готовое решение GeeTest — это набор из трёх значений: challenge, validate и seccode.
На 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"
# }
На Node.js — аналогичный цикл через async/await:
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');
}
Как только status в ответе стал 1, решение уже готово — повторно опрашивать res.php для этой же задачи не нужно, task_id одноразовый и второй раз ничего не вернёт.
Шаг 4: передайте решение на целевой сайт
Все три значения уходят в форму или endpoint проверки самого сайта:
# Submit the GeeTest solution with the form data
verify_response = requests.post("https://example.com/api/login", data={
"username": "[email protected]",
"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}")
Сколько потоков закладывать под нагрузку
Число одновременных запросов, которое реально нужно, определяется параллелизмом ваших сценариев, а не общим количеством решений: CaptchaAI тарифицирует именно по потокам, и внутри одного потока решения не ограничены. Для одиночного QA-прогона или единичной формы логина обычно достаточно младшего плана; для параллельного парсинга нескольких сайтов или пиковой нагрузки в очереди CI считайте по числу одновременно открытых задач, а не по трафику в целом. Актуальные тарифы и число потоков на каждом плане смотрите в личном кабинете CaptchaAI.
Отдельный практический момент — тайминг. Опрос res.php — самая частая точка отказа в проде: если сеть нестабильна (мобильный аплинк, VPN, регион с высоким RTT до ocr.captchaai.com), 5-секундный шаг и 30 попыток — разумный дефолт, но при частых таймаутах увеличивайте именно интервал между попытками (до 7–8 секунд), а не их количество — задача GeeTest всё равно одноразовая, и лишние попытки на уже решённый challenge ничего не дадут.
Полный пример на Python
import requests
import time
API_KEY = "YOUR_API_KEY"
SITE_URL = "https://staging.example.com/qa-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": "[email protected]",
"password": "pass",
"geetest_challenge": solution["geetest_challenge"],
"geetest_validate": solution["geetest_validate"],
"geetest_seccode": solution["geetest_seccode"]
})
print(f"Result: {login.status_code}")
Частые вопросы
Вкладка Network пустая — где ещё искать gt и challenge?
Проверьте исходный код страницы на вызов initGeetest (способ 2) — многие сайты передают параметры прямо в inline-скрипте, минуя отдельный сетевой запрос, который можно было бы поймать в DevTools. Если и там пусто, часть сайтов отдаёт параметры через собственный API регистрации виджета (способ 3) ещё до его отрисовки — тогда проще всего найти этот вызов в исходном коде фронтенда страницы логина или чекаута.
Сколько времени в среднем занимает решение GeeTest v3 через API?
Обычно менее 12 секунд, с высокой долей успешных решений на всех типах заданий v3 — слайд, значки и сопоставление слов идут через одинаковый API и занимают сопоставимое время решения. Закладывайте этот интервал в таймаут вызывающего кода, а не фиксированные 15–30 секунд из старых оценок.
Что делать при ошибке ERROR_CAPTCHA_UNSOLVABLE?
Это почти всегда означает, что challenge устарел или изначально был передан с ошибкой. Запросите у сайта новое задание целиком — старое переиспользовать нельзя, оно одноразовое, и повторная отправка того же challenge не поможет.
Появится ли у CaptchaAI поддержка GeeTest v4?
Пока нет — GeeTest v4 использует другой протокол проверки, и эта версия отдельно значится в разработке у CaptchaAI. Перед интеграцией уточните на самой странице, какую именно версию GeeTest использует сайт: v3 и v4 внешне похожи, но параметры и API несовместимы.
Обязательно ли передавать api_server, если сайт использует нестандартный домен?
Да, если он вообще фигурирует на странице: часть сайтов явно указывает нестандартный сервер проверки (например, api-na.geetest.com вместо api.geetest.com) — тогда это значение нужно передать вместе с запросом, иначе сервер, к которому обратится CaptchaAI, не совпадёт с тем, что использует сайт. Если в исходном коде такого значения нет, параметр можно не указывать — применится сервер по умолчанию.
Типичные ошибки и как их исправить
ERROR_BAD_PARAMETERS— не хватаетgtилиchallenge. Оба параметра обязательны, извлеките их со страницы заново одним из трёх способов выше.ERROR_CAPTCHA_UNSOLVABLE— срок действия задания истёк или оно было передано с ошибкой. Запросите у сайта свежее задание и повторите отправку с нуля.- Решение отклонено сайтом — вы отправили устаревшее значение
challenge. Задание одноразовое: получайте новое перед каждой попыткой, даже повторной. geetest_validateвозвращается пустым — решение не удалось внутри CaptchaAI. Повторите отправку с новымchallenge, не переиспользуя старый.
Готовый рабочий пример
Нужен полноценный проект с настройкой окружения, опросом, повторами и обработкой ошибок из коробки — без сборки с нуля?
Полный рабочий пример на GitHub →