API Tutorials

Как решить GeeTest v3 с помощью API

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 (самый надёжный):

  1. Откройте DevTools → вкладку Network.
  2. Отфильтруйте запросы по register-slide, gettype.php или get.php.
  3. Запустите капчу и найдите запрос инициализации.
  4. В ответе будут 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 →


Похожие материалы

Комментарии для этой статьи отключены.