Можно было бы написать так - “опытные разработчики, занимающиеся парсингом и автоматизацией, нередко сталкиваются с необходимостью обхода современных капч”. Но это слишком скучно… Я лучше начну так - продолжая изучать забавный мир капч, я в своих изучениях добрался таки до китайской версии защиты - GeeTest капчи. Давайте разбираться, что же это за зверь, где он обитает и почему нужно его опасаться… Или не нужно… В общем в процессе поймете!
GeeTest — один из продвинутых представителей антибот-систем, который сочетает в себе головоломки для пользователя и анализ его поведения. Я решил подробно рассмотреть распознавание капчи GeeTest в условиях боевых реалий и разобраться, как обойти GeeTest капчу различными методами. Но сначала - классическое вступление (которое, кстати, может быть интереснее, чем практическая часть статьи, так как обход GeeTest капчи для многих читателей уже является нетривиальной задачей).

Что такое GeeTest и почему эта капча сложная?
GeeTest (разработчик – китайская компания GeeTest) – это современная система CAPTCHA, предназначенная для защиты сайтов от ботов. В отличие от классических «Введите символы с картинки», GeeTest делает упор на интерактивные головоломки: например, пользователь должен передвинуть пазл (слайдер) или решить мини-игру. При этом система анализирует поведение пользователя (движения мыши, скорость решения, клики) и собирает обширную информацию об устройстве (т.н. device fingerprint). Все это осложняет автоматическое распознавание.
Особенность GeeTest – адаптивность: при подозрении на бота задачки усложняются. Например, реальному пользователю может попасться лёгкий одношаговый слайдер, тогда как подозрительному трафику система покажет серию сложных заданий. Такая многоуровневая защита значительно повышает барьер для обхода ботами.
Основные причины, почему обход GeeTest может оказаться фатальным для некоторых скриптов:
Интерактивность заданий. Требуется эмулировать реальное взаимодействие (перетаскивание ползунка, клики по объектам и т.п.), а не просто распознать текст или передвинуть слайдер из одного положения в другое.
Анализ поведения. GeeTest отслеживает траекторию движения курсора, паузы, резкость движений, попытки и др. Нетипичное, «роботизированное» поведение приведёт к провалу проверки.
Сбор “отпечатков” устройства. Капча собирает данные о браузере и системе: User-Agent, разрешение экрана, наличие плагинов, шрифтов, часовой пояс, Canvas/WebGL-отпечаток, и многое другое. Если эти параметры выглядят подозрительно (например, характерны для автоматизированного браузера), защита может либо усложнить задачу, либо вовсе блокировать попытку.
Обфускация и проверка на стороне сервера. Скрипты GeeTest сильно обфусцированы (особенно в v4), а итоговое решение проверяется на сервере через токены. Нельзя просто угадать положение пазла – нужно правильно сформировать ответ, который сервер сочтёт валидным.
Таким образом, GeeTest представляет собой серьезный вызов для разработчиков, занимающихся парсингом и автоматизацией. Но возможности обойти эту капчу все же есть – далее рассмотрим, какие.
Версии GeeTest v3 vs v4: эволюция капчи
GeeTest прошла несколько итераций, и наиболее распространены версии v3 и v4. Понимание их отличий важно для выбора метода обхода.
GeeTest v3 (классическая версия) – демонстрирует пользователю видимую капчу (чаще всего слайдер-пазл). Инициализация капчи происходит с помощью двух параметров, которые присутствуют в коде страницы:
gt
– ID сайта в системе GeeTest (публичный ключ).challenge
– уникальная строка-челлендж для текущей сессии.
На странице обычно подключается скрипт gt.js с сервера GeeTest, и при решении отправляются запросы вида /get.php
и /validate.php
на сервер GeeTest. В версии v3 предусмотрено несколько видов заданий: Slide CAPTCHA (пазл-слайдер), Icon CAPTCHA (выбор/перетаскивание иконок), Space CAPTCHA и т.д. – о них ниже.
GeeTest v4 (так называемая Adaptive CAPTCHA) – новая версия, появившаяся позже, с улучшенной гибкостью и невидимыми режимами. Ключевые отличия:
Вместо пары
gt
+challenge
используется один параметрcaptcha_id
(аналогgt
), а все прочие параметры включаются в объектinitParameters
при инициализации. Проще говоря, фронтенд-код вызывает функциюinitGeetest4
с объектом опций, где основное – этоcaptcha_id
.Скрипты загружаются с путями, содержащими
/v4/
(например,gcaptcha4.js
), что заметно при анализе трафика.Adaptivity: v4 динамически подстраивает сложность. Если пользователь выглядит “чистым”, капча может сработать в тихом режиме (практически незаметно). У v4 есть режим NoCaptcha, когда достаточно нажать одну кнопку «Verify» – фоновые проверки уже убедились, что вы человек. Но для подозрительного пользователя GeeTest v4 выставит серию трудных испытаний (например, несколько этапов).
Протокол v4 более сложный: данные о взаимодействии пользователя упаковываются и шифруются перед отправкой на сервер. Например, в v4 присутствует параметр w – зашифрованный «ответ», содержащий всю информацию о действиях пользователя, времени, и проч. Этот параметр рассчитывается специальным образом (в obfuscated-скрипте), и его значение сложно подделать без полного воспроизведения логики.
Определить версию на сайте можно по коду страницы и сетевым запросам. Если видим упоминание gt
и challenge
– перед нами v3. Если же капча загружается через gcaptcha4.geetest.com
и фигурирует captcha_id
– это v4. Для примера, при загрузке v4 часто встречается URL вида:
https://gcaptcha4.geetest.com/load?captcha_id=<ID>&challenge=<UUID>
Здесь captcha_id
– ключ, а challenge генерируется динамически на каждый кейс. В v3 же challenge можно обнаружить прямо в HTML или инициализационных данных страницы.
Вкратце:
GeeTest v3 – старый вариант, видимая капча, параметры
gt
+challenge
, основной тип – слайдер.GeeTest v4 – новый вариант, адаптивная (часто невидимая), основной параметр
captcha_id
, больше видов задач, сложнее эмулировать протокол.
Типы задач GeeTest: слайдер, иконки, “пятнашки” и мини-игры
За годы GeeTest представила множество видов CAPTCHA-челленджей. Вот основные из них, с которыми может столкнуться разработчик:
Slide CAPTCHA (пазл слайдер). Классика GeeTest: изображение с вырезанным фрагментом и отдельный кусочек-пазл. Пользователь должен перетащить ползунок, чтобы кусочек идеально встал в выемку на картинке. Эта задача выглядит простой, но система оценивает, насколько плавно и человечно вы двигали пазл. Задача для бота: определить смещение вырезанного фрагмента и имитировать человеческое движение курсора. Слайдер-капча присутствует и в v3, и в v4 (в v4 она тоже остается самым распространенным типом испытания).

Click/Icon CAPTCHA. Вариант, где пользователю показываются изображения или иконки, и нужно кликнуть по всем, соответствующим заданию. Пример: «Найдите все кошки среди этих картинок» или интерфейс с несколькими иконками, где надо выбрать указанные. В контексте GeeTest Icon CAPTCHA обычно означает задание: «кликните по объектам в правильном порядке» или перетащите значки по соответствию с тенями. При этом GeeTest фиксирует координаты кликов и время между ними. В v3 Icon CAPTCHA встречалась реже, в v4 – она была улучшена с технической точки зрения.

IconCrush CAPTCHA. Оригинальный тип из арсенала v4. Пользователю показывается сетка значков (иконок) как в игре «три в ряд», и требуется выбрать три одинаковых значка подряд. По сути, мини-игра: нужно найти на поле одинаковые иконки и кликнуть их, составляя ряд. Идея – сделать капчу веселой для пользователя, но очень трудной для бот-скриптов, ведь требуется анализ изображения и понимание, какие элементы одинаковые. Для бота это задача компьютерного зрения: распознать каждый маленький значок и найти тройку одинаковых.

Gobang CAPTCHA. Ещё более необычный вариант (назван в честь игры «五子棋» – Gobang, известной как «пять в ряд»). Пользователь участвует в мини-игре: ставит фишки, пытаясь выстроить пять подряд на доске. Фактически, решает простейшую головоломку. GeeTest может использовать Gobang при повышенной подозрительности, как сложный интерактивный барьер. Для бота решить Gobang означало бы либо полностью симулировать игру (что очень нетривиально), либо… не доводить до такого уровня проверки (т.е. пройти капчу пораньше и полегче).

Space CAPTCHA. В документации v3 упоминается Space CAPTCHA. Судя по описаниям, это тоже вариант с кликами: например, нужно расставить объекты в правильные положения (занять "пробелы"/ниши). Точных деталей, как может выглядеть этот тип капчи у меня мало, но задача аналогична — проверить динамику действий пользователя при размещении объектов. Мне подобная капча не встречалась, ну либо я не понял что это именно она, точной иллюстрации мне также найти не удалось.
NoCAPTCHA (OneTap). Режим, в котором от пользователя требуется просто нажать кнопку «Я не бот» (аналог reCAPTCHA v2 Checkbox). Однако за кулисами GeeTest проводит обширные проверки: анализирует поведение до клика, отпечатки браузера, возможно, выполняет скрытый JavaScript-тест или даже Proof-of-Work. Если всё выглядит хорошо и нет подозрений, что перед капчей бот, то одного клика достаточно, чтобы пройти капчу. Если нет — после клика может выскочить полноценное задание (слайдер или другое). NoCAPTCHA чаще доступен обычным пользователям; для нас интересно, что GeeTest v4 может вообще не показывать визуальной головоломки, если уверен в “человечности” трафика.

GeeTest постоянно экспериментирует. Могут быть и другие типы заданий (например, Image CAPTCHA – подбор фрагментов изображения по порядку, или аудио-капча как альтернатива для людей с ограничениями зрения). Но вышеперечисленные — наиболее известные и показательные с точки зрения обхода.
Как GeeTest определяет бота: поведение и отпечатки
Прежде чем перейти к методам решения, важно понять, какие сигналы GeeTest использует для отличия ботов от людей. Зная это, вы сможете грамотно эмулировать человека (или не сможете, тут уже все будет зависеть от ваших навыков, у меня были и такие и такие кейсы в практике).
Поведенческий анализ. Каждый этап взаимодействия с капчей отслеживается. Например, для слайдера записывается траектория курсора: координаты X/Y каждую миллисекунду, рывки, остановки. Если движение слишком прямолинейно, без микро-колебаний — похоже на скрипт. Если курсор перемещается идеально по прямой, с постоянной скоростью или телепортируется — явно бот. Также фиксируется время реакции: человек не начнёт тянуть ползунок в точную миллисекунду после загрузки виджета, а бот может. Для клик-капчи отлавливается порядок и скорость кликов. Например, Icon CAPTCHA проверяет, как быстро и аккуратно вы перетащили нужные иконки: слишком высокая скорость и идеальная точность наведения могут насторожить систему. Все эти данные отправляются на сервер (в v3 частично в открытом виде, в v4 – внутри зашифрованного w).
Device Fingerprinting (цифровой отпечаток устройства). GeeTest собирает информацию о браузере через JavaScript:
Параметры экрана: разрешение, цветовая глубина, размеры viewport.
Данные браузера: User-Agent, наличие webdriver (признак
WebDriver
), список плагинов и MIME-типов, платформа, язык, часовой пояс.Canvas/WebGL-фингерпринт: скрыто рисует что-то на
<canvas>
и считывает пиксели (у разных систем получается чуть разный рисунок), проверяет WebGL-рендерер.Аудио-данные: может создавать AudioContext и собирать небольшие отличия в генерируемом звуке.
Шрифты: скрыто перечисляет установленные шрифты.
В совокупности эти данные образуют уникальный «отпечаток». Если бот повторно идёт с тем же отпечатком, его могут вычислить. Или если отпечаток очень уж редкий (например, headless-браузер обычно выдает нестандартные данные), то система насторожится. Пример: самый распространенный инструмент для автоматизации - Headless Chrome, у которого
property navigator.webdriver=true
— GeeTest наверняка это проверит и может сразу усилить защиту.Сетевая информация (IP, Proxy). Не последнюю роль играет и сетевой «отпечаток»: IP-адрес пользователя, его геолокация, принадлежность к прокси/дата-центру. Если IP известен как VPN или датацентр, капча покажется практически всегда. Если с одного IP идут десятки попыток за минуту — явный ботнет/скрипт. GeeTest может обмениваться данными с другими антибот-системами или использовать собственные репутационные базы IP.
Общие эвристики. Помимо вышеуказанного, GeeTest, как и reCAPTCHA, использует машинное обучение на больших данных. Анализируются сотни параметров на стороне сервера (включая даже время загрузки ресурсов, порядок вызова функций JS, производительность устройства и т.п.). Например, время между событиями: человек не сможет кликнуть 10 раз в разные места за 0.1 секунды. Или случайные движения: человек обычно чуть поводит мышью перед началом задачи, может промахнуться сначала. Бот же часто действует слишком прямолинейно.
В результате GeeTest формирует некий score доверия или сразу решает кто прошёл капчу - пользователь или бот. Если поведение аномальное – либо даётся более сложная задача, либо вообще проверка считается не пройденной несмотря на правильный ответ. Поэтому основная цель при обходе – не только найти правильное решение головоломки, но и выглядеть при этом максимально естественно.
Подходы к распознаванию и обходу капчи GeeTest
Переходим к самому интересному: методы обхода GeeTest. Универсального решения «на все случаи» не существует – многое зависит от версии капчи, типа задачи и уровня антибот-защиты на конкретном сайте. Рассмотрим несколько подходов, которые можно комбинировать:
1. Использование сторонних сервисов (RuCaptcha, 2Captcha, SolveCaptcha и др.)
Самый простой путь для разработчика – передать задачу распознавания капчи внешнему сервису. Существуют специализированные сервисы типа RuCaptcha/2Captcha, SolveCaptcjha и др., которые либо привлекают реальных людей для решения, либо используют собственные ML-модели. Вам достаточно отправить через API параметры капчи – в ответ придёт готовое решение (токены), которое можно подставить на сайт.
Как это работает? Например, для 2Captcha:
Вы извлекаете с целевой страницы необходимые данные. Для GeeTest v3 это
gt
,challenge
и адрес страницы. Возможно, также поддомены API (если используются нестандартные, обычно по умолчанию api.geetest.com). Для GeeTest v4 достаточноcaptcha_id
и адрес страницы;challenge
сервис получит сам при решении.
Отправляете POST-запрос на сервер 2Captcha, указывая метод решения geetest. В параметрах передаются нужные ключи. Например, с использованием requests в Python:
import requests, time
API_KEY = "ВАШ_2CAPTCHA_APIKEY"
website_url = "https://пример-сайта-с-капчей.com/page"
gt = "81388ea1fc187e0c335c0a8907ff2625" # значение gt (для v3)
challenge = "2e2f0f65240058b683cb6ea21c303eea6n" # значение challenge (для v3)
# 1. Отправляем задачу распознавания на 2Captcha
payload = {
'key': API_KEY,
'method': 'geetest',
'gt': gt,
'challenge': challenge,
'pageurl': website_url
}
resp = requests.post("http://2captcha.com/in.php", data=payload)
if resp.text.startswith("OK|"):
captcha_id = resp.text.split('|')[1]
else:
raise Exception(f"Ошибка API 2Captcha: {resp.text}")
# 2. Периодически опрашиваем результат
result = None
result_url = f"http://2captcha.com/res.php?key={API_KEY}&action=get&id={captcha_id}"
for i in range(20):
time.sleep(5) # ждем 5 сек перед каждым опросом
res = requests.get(result_url)
if res.text == "CAPCHA_NOT_READY": # (да, опечатка в ответе API 2Captcha)
continue
if res.text.startswith("OK|"):
result = res.text.split('|', 1)[1]
break
if not result:
raise Exception("Не удалось получить решение капчи в отведенное время")
print("Решение GeeTest:", result)
В случае v3 сервис обычно возвращает строку формата JSON с полями challenge
, validate
, seccode
. Для v4 может возвращаться чуть другой формат (например, просто captcha_output
токен) – детали есть в документации сервиса.
Применение решения: полученные от сервиса данные нужно отправить обратно на сайт где вы обходите капчу. Как правило, на странице есть скрытая форма или скрипт, ожидающий, что вы установите результат капчи. Например, для v3 зачастую нужно подставить три скрытых поля (geetest_challenge
, geetest_validate
, geetest_seccode
) и отправить форму. Для v4 – может требоваться вызывать JS-функцию подтверждения или устанавливать токен. В простейшем случае можно имитировать браузер: заполнить document.getElementById('geetest_challenge').value =
... и т.д., затем выполнить нужный callback
.
Плюсы метода: минимальные усилия – всю сложную работу берёт на себя сервис. Решение обычно занимает от 5 до 20 секунд (для человека) или пару секунд (если ML). Стоимость тоже невысока: ~$0.001-$0.002 за капчу (1-2 доллара за 1000 решений) в случае RuCaptcha/2Captcha.
Минусы: зависимость от внешнего сервиса: возможны задержки, нужно тратить деньги. Кроме того, некоторые сложные капчи (Gobang, сложные IconCrush) могут неправильно решаться автоматикой. Тогда сервис может вернуть ошибку или затянуть по времени, пока подключат реального человека.
Совет: используйте сервисы с умом. Например, 2Captcha позволяет распознавать GeeTest как proxyless
(свои прокси не нужны) или с вашими прокси. Proxyless проще, но иногда сайт привязывает капчу к IP решающего. Если заметили, что решения не принимаются сайтом, попробуйте использовать метод с передачей вашего прокси в сервис распознавания капчи (т.е. чтобы работник 2Captcha решал капчу "с вашего IP"). RuCaptcha/2Captcha это поддерживает через метод GeeTestTask/GeeTestTaskProxyless
.
Кроме того, на рынке есть инструменты типа SolveCaptcha – это сервис, который решает капчи с помощью нейросетей (и только если не получается обойти капчу нейросетью, тогда подключаются люди). Оно тоже платное, но при большом объёме может быть выгоднее. Концепция та же: вы отправляете им изображения или параметры – получаете ответ.
Итог: подключение внешнего сервиса – отличный вариант для быстрого прототипа или небольшого парсинга (или большого). Многие не идут дальше этого, автоматизируя лишь обёртку вокруг API. Но если хочется большей автономности или скорости – есть более «хардкорные» подходы.
2. Решение с помощью OpenCV и алгоритмов компьютерного зрения
Следующий подход – попытаться научить код решать капчу самостоятельно. Это особенно применимо к графическим задачам, таким как слайдер-пазл. Идея: скачать изображения, проанализировать их (например, найти вырезанный фрагмент на фоне) и вычислить нужное действие (например, смещение ползунка в пикселях).
Самый распространённый кейс – автоматическое решение слайдер-капчи. У нас есть два изображения: фон с вырезанной фигурой и сама фигура-пазл. Задача: найти, куда на фоне вставляется кусок. Можно использовать библиотеку OpenCV (Computer Vision), чтобы определить смещение по X.
Простой подход через шаблонное сопоставление (template matching):
Конвертируем фон и фрагмент в
grayscale
, при необходимости усиливаем контраст или используем детектор краёв (Canny), чтобы контуры выемки были явными.Применяем
cv2.matchTemplate
, чтобы найти участок фона, наиболее похожий на изображение кусочка. Эта функция сверяет шаблон (кусочек) с каждым положением на исходном изображении (фон) и выдаёт карту совпадений. Пиксель с наибольшим коэффициентом совпадения – вероятное место вставки.Получаем координаты этого лучшего совпадения – это и будет положение для пазла.
Ниже пример кода на Python, иллюстрирующий этот подход:
import cv2
import numpy as np
# Загружаем изображения (например, сохраненные ранее)
background = cv2.imread("captcha_bg.png", 0) # фон (серый 0 - grayscale)
template = cv2.imread("captcha_piece.png", 0) # кусочек пазла
# Улучшаем изображения: применим детектор границ, чтобы акцентировать форму выреза
bg_edges = cv2.Canny(background, 50, 150)
tpl_edges = cv2.Canny(template, 50, 150)
# Ищем шаблон на фоне
result = cv2.matchTemplate(bg_edges, tpl_edges, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(result)
match_x, match_y = max_loc
print(f"Найдена позиция для вставки: X={match_x}px, Y={match_y}px (совпадение {max_val:.2f})")
Предположим, match_x
– смещение по горизонтали, где должен встать левый край кусочка. Чаще всего нам и нужен именно X (по Y кусок обычно фиксирован по вертикали). Далее остаётся эмулировать движение ползунка на это расстояние.
Важно: непосредственно отправлять координаты на сервер GeeTest бессмысленно – нужно повторить человеческое действие. Здесь на помощь приходит браузерная автоматизация: Selenium, Puppeteer, Playwright и т.п. Мы можем запустить браузер (желательно, максимально неотличимый от обычного), открыть страницу с капчей и с помощью кода сгенерировать события мыши – нажать и удерживать ползунок, “протащить” его на match_x
пикселей.
Например, на Selenium (Python) можно использовать ActionChains
для плавного драга:
from selenium.webdriver import ActionChains
slider = driver.find_element(By.CSS_SELECTOR, ".geetest_slider_button") # элемент ползунка
ActionChains(driver).click_and_hold(slider).perform()
# Далее движем с разными дельтами, имитируя человеческую кривую
import math, random
distance = match_x
current = 0
while current < distance:
# на каждом шаге продвигаемся на случайную величину с небольшим разбросом
step = random.randint(5, 8) # шаг в пикселях (иногда большой, иногда маленький)
if current + step > distance:
step = distance - current
ActionChains(driver).move_by_offset(xoffset=step, yoffset=0).perform()
current += step
# небольшая пауза
time.sleep(random.uniform(0.01, 0.03))
# Небольшой возврат назад (человеку свойственны микро-движения)
ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform()
time.sleep(0.1)
ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform()
# Отпускаем кнопку
ActionChains(driver).release().perform()
Код выше лишь вариант – он создаёт серию небольших перемещений на 5-8 пикселей, с короткими паузами, и даже имитирует дрожание (чуть отодвигает назад перед финальным положением). В результате курсор пройдет путь из, скажем, 150 пикселей не мгновенно, а за ~30 шагов с неровной скоростью. Это более похоже на человеческое движение, чем простое move_by_offset(150,0)
.
Если всё сделано правильно, GeeTest на стороне браузера отрисует движение, отправит траекторию на сервер и вернёт validate/seccode
токены, подтверждающие успех решения. Selenium/Browser
увидит, что капча пройдена, и можно продолжить работу (запрос страницы или отправка формы).
Я сам пробовал этот способо и после нескольких бубнотанцев это сработало, но надо докручивать под свою задачу, это очевидно.
Computer Vision также может применяться для других типов задач: например, IconCrush
– тут потребовалось бы распознать иконки (возможно, с помощью шаблонов или даже нейросети), или Gobang
– распознать доску и логику игры (что уже сильно сложнее). В некоторых случаях, вместо полного распознавания, разработчики идут по пути упрощения: заранее собрать множество вариантов заданий. Так сделали разработчики одного приватного решения со слайдером – они обнаружили, что GeeTest использует ограниченный набор фоновых картинок и скачали тысячи вариантов, вручную определили для каждого правильную позицию вставки, и сохранили в базу хеш -> смещение. Затем бот мог просто сравнить хеш текущей картинки с базой и мгновенно получить ответ (если картинка была в базе). Однако, такая база со временем устаревает, и ее необходимо регулярно пополнять новыми картинками.
Достоинства подхода OpenCV/ML: независимость от сторонних сервисов, мгновенное решение (получаем ответ за доли секунды), полный контроль над процессом. При отладке можно визуализировать, понимать, где сбоит.
Недостатки: нужно писать и поддерживать код решения под каждый тип капчи. Если GeeTest поменяет дизайн или логику, скрипт придется переписывать. Также сложные типы (Gobang) вряд ли легко решить без полноценного ИИ. Поэтому на практике CV-подход почти всегда используется для слайдера – как наиболее типового и понятного визуально.
Я считаю, что совмещение подходов – мощная вещь. Например, можно сначала попытаться решить через OpenCV, а если не получилось (капча не стандартная или несколько попыток провалены) – тогда отправлять задачу на 2Captcha как резервный вариант. Это повысит и скорость (меньше обращений к стороннему сервису), и успех обхода, да и деньги сэкономит.
3. Браузерная автоматизация и имитация пользователя (Selenium, Puppeteer)
Строго говоря, мы уже использовали браузер в предыдущем разделе для применения решения. Но бывает, что разработчик использует стратегию: не распознавать капчу, а постараться грубо пройти, эмулируя пользователя.
Например, представим, что у нас нет OpenCV или денег на сервис распознавания капчи (но есть жгучее желание ее обойти и много времени). Мы можем запустить реальный браузер (Chrome/Firefox) под управлением скрипта, дождаться появления виджета GeeTest и попробовать автоматически выполнить требуемое действие. В случае слайдера – попытаться перетаскивать ползунок на разные расстояния, пока не будет успеха. В случае Icon CAPTCHA – возможно, проанализировать HTML (вдруг там подсказки) или использовать селекторы. Иногда виджет может содержать текст-подсказку (например, alt-теги изображений) – маловероятно, но вдруг.
Проще говоря, этот подход сводится к написанию сценария для инструмента типа Puppeteer (Node.js) или Selenium/Playwright (Python/JS), который воспроизводит действия пользователя. Сочетая его с небольшими эвристиками, можно решить некоторые капчи. Пример: для слайдера – пытаться двигать ползунок на +5 пикселей, проверяя, не прошло ли (GeeTest сообщает об ошибке, если пазл не на месте, можно повторить). Однако, GeeTest обычно ограничивает число попыток и усложняет при каждой неудаче, так что брутфорс в лоб – плохая идея. Но если вы упорный джун, можно попробовать. На многопотоке такой способ конечно плохая идея, но исключать такой метод тоже нельзя, он существует.
Более реальный сценарий – комбинировать автоматизацию с внешним решением. Именно так делают некоторые разработчики: с помощью Puppeteer открывают страницу, извлекают параметры gt/challenge и отправляют их на 2Captcha, получив ответ – вставляют его обратно через браузер. Это позволяет преодолеть некоторые хитрости фронтенда: например, сайт может ожидать, что решение капчи будет введено в открытой странице (для v3 – поля формы, для v4 – выполнение captchaObj.submit()
например).
Код на Node/Puppeteer может выглядеть так (упрощенно):
// Находим параметры на странице
const gt = await page.evaluate(() => window.gt);
const challenge = await page.evaluate(() => window.challenge);
// ...либо ловим сеть
// Отправляем на 2Captcha API (можно через fetch)
const solveResponse = await solveGeeTest(gt, challenge, page.url()); // предположим, такая функция есть
const { challenge: ch, validate, seccode } = solveResponse;
// Вставляем в страницу скрытые поля или вызываем cb
await page.evaluate((ch, val, sec) => {
document.getElementById('geetest_challenge').value = ch;
document.getElementById('geetest_validate').value = val;
document.getElementById('geetest_seccode').value = sec;
// триггерим событие успешного решения (например, отправка формы)
document.querySelector('form#geetest-demo-form').submit();
}, ch, validate, seccode);
Такой гибридный подход взял лучшее от обоих миров: браузер открывает страницу как обычный пользователь (с исполняемым JS, что может быть необходимо для полной инициализации капчи), а решение получаем от внешнего сервиса или CV-алгоритма.
Однако, автоматизация браузера требует антидетекта! Простое использование Selenium в headless-режиме с дефолтными настройками, скорее всего, выявится. GeeTest может проверить свойства браузера, и Selenium выдаёт себя (например, наличие navigator.webdriver
, характерные DevTools CDP
заголовки, отсутствие реальных плагинов и др.). Аналогично Puppeteer: без специальных мер (как puppeteer-extra-plugin-stealth
) Chrome будет в «headless
» режиме, что легко узнать.
Поэтому, если идете этим путём:
Используйте “stealth” плагины и патчи. Для Puppeteer есть набор плагинов, отключающих большинство известных флажков автоматизации. Для Selenium можно применять специальный
undetected_chromedriver
или режим запуска с включенным UI (не headless), а также убирать признаки автоматизации (например, выполнить JS, делающийdelete navigator.webdriver
или подменить свойства).Настраивайте параметры, как у обычного пользователя. Задайте обычный User-Agent. Добавьте фейковые плагины (есть скрипты, которые присваивают
navigator.plugins
какой-то список заглушек). Установите нужный часовой пояс и язык в браузере, соответствующие прокси региону.Эмулируйте ввод аккуратно. Вместо мгновенных
.click()
лучше использовать последовательность событий:mousemove
,mousedown
, маленькие сдвиги,mouseup
. Puppeteer позволяет синтезировать события ввода (mouse.move, .down, .up
). Сделайте перед началом небольшую паузу, будто человек думает.
Автоматизация браузера хороша тем, что приближает нас к реальному сценарию максимально. Мы, по сути, говорим: “пусть наш скрипт станет пользователем на уровне браузера”. И если всё сделано аккуратно, для сайта будет почти не отличимо от реального человека, особенно если само решение капчи правильное.
Минус – нужно поддерживать инфраструктуру (запускать браузеры, следить за их обновлениями, потребляется больше ресурсов по сравнению с чистым HTTP-запросом решения). Но для сложных случаев (например, Cloudflare
+ GeeTest
вместе) без полноценного браузера обойтись может быть невозможно.
4. Реверс-инжиниринг и эмуляция протокола GeeTest
Самый трудозатратный, но и самый “спортивный” способ – полностью разобраться, как работает GeeTest, и научиться подделывать ответы на низком уровне. Речь о том, чтобы эмулировать логику фронтенда и формировать ответы, которые сервер примет без фактического прохождения капчи в браузере.
В случае GeeTest это крайне непросто, ведь код их виджетов обфусцирован, а данные шифруются. Но талантливые ребята всё же пытались:
Для GeeTest v3 энтузиасты разбирали JS-файл
gt.js
. В нём реализовано формирование параметров, отправляемых на сервер (/validate.php
). Например, там вычисляется подпись движений мыши. В более старых версиях были известны уязвимости – можно было отправить пустой или фиксированный трек и получитьvalidate
без реального решения, но эти лазейки давно закрыты. Тем не менее, некоторые боты умели генерировать правдоподобные треки без браузера: просто алгоритмически (случайный разброс вокруг плавной кривой) и вместе с правильным вычислением контрольных сумм.Для GeeTest v4 задача усложнилась. Код
gcaptcha4.js
шифрует взаимодействие, включая ту самую строку w (огромный блок данных). Разработчики на Reddit сообщали об успешномreverse-engineering v4
: через кропотливый анализ JS выяснили, как формируется w, включая парсинг траектории (названныйlotParser
) и применениеAES/RSA
шифрования. В результате им удалось воспроизвести этот процесс в Python и научиться получатьvalidate
, зная лишь исходные изображения и желаемое движение. По сути, они обошли необходимость в реальном браузере.
Однако любые публичные успехи быстро приводят к контрмерам: GeeTest меняет обфускацию, добавляет поля в протокол, обновляет алгоритмы. Поэтому решение через чистый реверс – это постоянная гонка. Малейшее изменение может сломать ваш скрипт.
Тем не менее, понимать протокол полезно. Иногда можно найти нестандартный путь. Например, обнаружить, что при определённых условиях сайт предоставляет альтернативную капчу. (Например, если отключен JS, сайт мог бы показать простую текстовую капчу – маловероятно с GeeTest, но вдруг). Либо заметить, что GeeTest-скрипт отдаёт по определённому URL нужные данные (скажем, изображения пазла) и их можно дернуть напрямую (отсылка к уже приведенной выше информации о том, как разработчики собрал все варианты картинок слайдера и решил задачу через банальный поиск по хешу, без OpenCV вообще). По сути, это тоже своего рода реверс-инжиниринг – использование внутренней “лени” системы, повторного использования ресурсов.
По моему мнению реверс-инжиниринг GeeTest – путь для энтузиастов и тех, кому критична каждая миллисекунда или полный контроль. Это требует большого опыта и времени. В промышленной среде чаще выбирают комбинацию первых трёх методов (сервисы + CV + браузер), оставляя полный реверс на крайний случай.
Антидетект: маскируем бота под человека
Независимо от выбранного метода решения, есть набор общих рекомендаций, которые помогут не выдать себя ботом при обходе GeeTest:
Используйте релевантные прокси. Идеально – резидентские или мобильные IP, географически соответствующие ожидаемой аудитории сайта. Избегайте публичных прокси и однотипных датацентров. Если вы решаете капчу через сервис, учтите, что решение придёт с другого IP – иногда сайт может сопоставить и отвергнуть его. В таких случаях лучше решать капчу через тот же IP (свои прокси на 2Captcha и аналогах).
Следите за заголовками и параметрами HTTP. Некоторые антибот-системы (поверх капчи) могут отслеживать не только капчу. Например, перед решением капчи сайт мог бросить JavaScript challenge, и ваш автоматический клиент может его не пройти. Поэтому старайтесь использовать либо полноценный браузер, либо точно эмулировать все необходимые запросы (включая загрузку скриптов GeeTest). Библиотек типа
requests
+fake-useragent
может не хватить, если потребуютсяcookies
, особые заголовки вродеSec-Fetch-Mode
,Accept-Language
и т.п., которые ставят браузеры.Настройте окружение браузера (при его использовании). Уже упоминалось:
Puppeteer Stealth Plugin
,undetected_chromedriver,
Playwright с режимом приведенияenvironment
кnon-headless
. Также, можно применять anti-detect браузеры: например, Multilogin, Dolphin{anty}, Mimic – они позволяют создавать профили с реальными отпечатками. Это платные решения (если использовать более определенного количества профилей (например в Dolphin можно сгенерить до 10 профилей бесплатно), но с их помощью можно запускать браузер с нужными параметрами и управлять им через Selenium/Puppeteer.Генерируйте правдоподобные события ввода. В особенности это касается сценария, где вы сами двигаете мышь. Скрипты, генерирующие идеально линейные траектории с постоянной скоростью, будут палиться. Вместо этого используйте кривые Безье, небольшие случайные отклонения, вариативные задержки. Имитация дрожания или корректировки – большой плюс (человек редко попадает идеально с первого раза, часто слегка корректирует позицию перед отпусканием пазла).
Учитывайте тайминги. Например, время начала решения: если ваш бот перехватил картинки и вычислил смещение за 0.1 секунды после загрузки – это подозрительно. Можно специально подождать 1-2 секунды перед движением, как будто пользователь посмотрел, прицелился. Или при кликах по объектам – делайте небольшую паузу между кликами, не нажимайте 5 целей за одну секунду. Даже реакцию на появление капчи можно рандомизировать (человек может не сразу приступить, а через ~0.5с).
Обновляйте сигнатуры. То, что работает сегодня, завтра может сломаться. Например, вдруг GeeTest начнёт проверять наличие свойств, которые ваш anti-detect пока не подменяет. Нужно мониторить изменения: следить за новостями (Habr, форумы blackhatworld, reddit /r/webscraping), анализировать сетевые логи при сбоях — не появились ли новые параметры.
Лимитируйте попытки. Не пытайтесь бесконечно решать капчу в рамках одной сессии. GeeTest может начать усложнять задачи экспоненциально. Логично после 2-3 неудачных попыток сменить IP/сессию и заново зайти. Также, если парсите массово, распределяйте нагрузку: не шлите 100 решений с одного IP подряд.
Обход капчи GeeTest – нелёгкая задача, но при грамотном подходе выполнимая. Мы рассмотрели и быстрые решения через сторонние сервисы, и более тонкие методы с OpenCV и эмуляцией пользователя. В каждом случае ключ к успеху – маскировка под реальное взаимодействие человека. GeeTest, как и другие капчи, – это постоянная игра в кошки-мышки: разработчики защиты усложняют механизмы, разработчики ботов адаптируются и ищут уязвимости.
Для опытного инженера такая задача может даже стать увлекательной: здесь и компьютерное зрение, и реверс-инжиниринг, и навыки веб-автоматизации. Применяя комбинированно описанные подходы (например, браузер + внешнее API, или OpenCV + эмуляция ввода) можно достичь высокой эффективности распознавания капчи GeeTest.
Будьте готовы учиться на каждом новом витке: появится GeeTest v5 – что ж, разберём и её! А пока – успешного парсинга и автоматизации, и пусть ни одна капча не помешает интересным проектам.