API — Распознавание капч
Отдельный слушатель, говорящий на протоколе anti-captcha.com: направьте на него стороннее ПО и решайте картинки, куки доступа, RCv2, CFt, GT и AW через свои прокси.
Что это
BlankTrail Proxy умеет принимать задачи на распознавание капч по протоколу anti-captcha.com. Это отдельный слушатель на своём порту: стороннее ПО, уже умеющее работать с этим протоколом, достаточно направить на ваш адрес вместо адреса сервиса распознавания.
Слушатель отдельный, а не маршруты на порту панели, по двум причинам. Официальные клиенты протокола бьют в корень хоста, то есть занимают корневые пути целиком. И капча-API вполне может понадобиться в локальной сети там, где панель управления не должна быть видна никому.
Как включить
Три поля в разделе captcha_api файла настроек. Рубильник и адрес можно поменять и в панели: «Настройки» → карточка «Капча-API».
captcha_api:
enabled: true
addr: ":8892"
allow_lan: false
max_concurrent: 10
task_ttl: "5m"
port_idle_timeout: "10m"
| Поле | Что делает |
|---|---|
| enabled | Поднимать ли слушатель. По умолчанию нет. |
| addr | Адрес слушателя. Пустой хост означает петлю, пока LAN не разрешён. |
| allow_lan | Принимать запросы не с этой машины даже при выключенной общей «Разрешить LAN». Капча-API следует этой общей настройке панели, а поле открывает его сверх неё — отдельно от прокси-портов. В образе Docker включено. |
| max_concurrent | Потолок одновременных задач. Ноль означает отсутствие потолка. |
| task_ttl | Сколько хранить готовый ответ после завершения задачи. |
| port_idle_timeout | Через сколько простоя закрывается порт, открытый под прокси задачи. |
В контейнере
В образе всё, кроме рубильника, уже настроено: порт 8892 объявлен, поставляемые compose-файлы публикуют его на 127.0.0.1, а конфиг образа разрешает слушателю привязку не к петле. Остаётся включить — переменной либо прямо в панели. Перекрытие переменными одностороннее: они включают и задают, но не гасят включённое в конфиге.
docker run -d \
-e BT_CAPTCHA_API_ENABLED=1 \
-p 127.0.0.1:8892:8892 \
... blanktrail-proxy
Ключ и доступ
clientKey — это ключ API вашей панели, тот же самый. Отдельного ключа для капча-API нет: заводить вторую тайну с собственным хранением и ротацией ради одной поверхности незачем.
- Ключ приезжает в ТЕЛЕ запроса, как того требует протокол, а не в заголовке.
- Подбор ключа ограничивается: после серии неудач адрес получает отказ независимо от того, верен ли следующий ключ.
- Запросы не с этой машины отвергаются, пока LAN не разрешён — общей настройкой «Разрешить LAN» или полем allow_lan, — включая getQueueStats и test.
Поддерживаемые типы задач
| Тип | Что делает |
|---|---|
| ImageToTextTask | Распознаёт текст на картинке локальной моделью. |
| AntiGateTask | Проходит защиту сайта и возвращает куки доступа. |
| RecaptchaV2Task | Решает RCv2 по адресу страницы и ключу сайта, через ваш прокси. |
| RecaptchaV2TaskProxyless | То же самое, но без вашего прокси — выход прямой. |
| TurnstileTask | Получает токен CFt по адресу страницы и ключу сайта, через ваш прокси. |
| TurnstileTaskProxyless | То же самое без вашего прокси. |
| GeeTestTask | Решает GTv3 или v4 по параметрам сайта, через ваш прокси. |
| GeeTestTaskProxyless | То же самое без вашего прокси. |
| AmazonTask | Проходит стену AW и возвращает её токен, через ваш прокси. |
| AmazonTaskProxyless | То же самое без вашего прокси. |
Прочие типы протокола отвечают ERROR_TASK_NOT_SUPPORTED. Это штатный ответ, а не сбой: клиент видит его сразу при создании задачи и может уйти к другому сервису, не тратя ожидания.
Варианты Proxyless решают с выхода самой установки — прямого адреса машины, на которой работает BlankTrail Proxy. Поля прокси, если они присланы, такие задачи не используют.
Как устроена работа
- Создаёте задачу через createTask и получаете числовой taskId.
- Опрашиваете getTaskResult, пока в ответе стоит processing.
- Получаете ready и объект решения — его состав зависит от типа задачи.
Выход и профиль
Все задачи, кроме ImageToTextTask, решает браузер решателя, и ходит он через порт продукта, открытый под прокси задачи. Это тот же путь, что у автоматического решения на прокси-порту. Запросы браузера уходят с выхода вашего прокси (у вариантов Proxyless — с выхода установки), с TLS- и HTTP/2-отпечатком и user-agent профиля этого порта. Токен или куки получены под той личностью, которую порт предъявляет сайту.
Порт открывается под пару «прокси плюс профиль» и живёт до простоя, заданного port_idle_timeout. Следующие задачи с тем же прокси и тем же профилем идут через него же.
Как выбирается профиль
Присланный userAgent не уезжает на провод. Он ВЫБИРАЕТ ближайший профиль по семейству браузера, мажорной версии и операционной системе, а на провод идёт user-agent этого профиля — вместе с согласованными с ним отпечатками TLS и HTTP/2.
Если userAgent не прислан или не распознан (Opera, Яндекс Браузер, Safari без токена Version/), порт получает Chrome для Windows новейшей версии из базы профилей — так же, как порт с профилем Chrome без заданной версии. У AntiGateTask и AmazonTask поля userAgent нет, и они всегда идут на этом профиле.
Каждая такая задача — попытка в карточке Challenge Breaker на дашборде, наравне с решениями на прокси-портах.
Распознавание картинки
Картинка передаётся в base64. Ответ несёт распознанный текст в поле text.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "ImageToTextTask",
"body": "iVBORw0KGgoAAAANSUhEUg..."
}
}
Куки доступа
AntiGateTask проходит защиту сайта и возвращает куки. Вместе с ними в ответе приезжает адрес порта, через который эти куки обязаны предъявляться.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiGateTask",
"websiteURL": "https://example.com/",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "pass"
}
}
RCv2
Задаче нужны адрес страницы и публичный ключ сайта. Вариант без вашего прокси называется RecaptchaV2TaskProxyless и полей прокси не требует.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "RecaptchaV2Task",
"websiteURL": "https://example.com/login",
"websiteKey": "6Lc_aCMTAAAAA...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080
}
}
Ответ — gRecaptchaResponse и userAgent (пример — у метода getTaskResult ниже).
CFt
Задаче нужны адрес страницы и ключ сайта (websiteKey — строка вида 0x4AAAA…). Необязательные action, cData и chlPageData передаются виджету как есть. Вариант без вашего прокси — TurnstileTaskProxyless.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "TurnstileTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "0x4AAAAAAA...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
}
}
Ответ — token и userAgent. Токен кладётся в поле cf-turnstile-response формы или отдаётся колбэку виджета; запрос с ним отправляйте с userAgent из ответа.
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "0.Zk3bE8...",
"userAgent": "Mozilla/5.0 ..."
}
}
GT
Поддержаны GTv3 и GTv4; версию задаёт поле version (3 или 4, по умолчанию 3). Вариант без вашего прокси — GeeTestTaskProxyless.
- v3: нужны gt и challenge сайта. challenge одноразовый — получайте его у сайта непосредственно перед созданием задачи. Необязательный geetestApiServerSubdomain задаёт сервер API, если сайт работает не с умолчанием GT.
- v4: нужен captchaId — в поле gt или в initParameters.captcha_id. Остальные initParameters передаются в initGeetest4 как есть.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "GeeTestTaskProxyless",
"websiteURL": "https://example.com/login",
"gt": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"version": 4,
"initParameters": {"riskType": "slide"},
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
}
}
Ответ v3 — challenge, validate и seccode; ответ v4 — captcha_id, lot_number, pass_token, gen_time и captcha_output. Вместе с ними приходит userAgent. Эти поля ваш запрос отправляет сайту, а сайт проверяет их у GT.
{
"errorId": 0,
"status": "ready",
"solution": {
"captcha_id": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"lot_number": "7c1b2a...",
"pass_token": "a8d9...",
"gen_time": "1790770800",
"captcha_output": "Qx3k...",
"userAgent": "Mozilla/5.0 ..."
}
}
AW
Задаче нужен адрес страницы, на которой сайт показывает стену AW. Поля websiteKey, iv, context, challengeScript и captchaScript принимаются для совместимости, но не нужны: всё это решатель берёт со страницы сам. Вариант без вашего прокси — AmazonTaskProxyless.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AmazonTask",
"websiteURL": "https://example.com/",
"proxyType": "http",
"proxyAddress": "203.0.113.7",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "pass"
}
}
Ответ — token и userAgent. token — значение куки aws-waf-token: поставьте её в свой запрос под этим именем и отправляйте его с userAgent из ответа. Поле ip в ответе getTaskResult — адрес выхода, с которого получен токен.
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "a1b2c3d4-...:AAABk...",
"userAgent": "Mozilla/5.0 ..."
},
"ip": "203.0.113.7"
}
Методы
/createTaskтребует clientKeyСоздаёт задачу и возвращает числовой taskId.
{
"errorId": 0,
"taskId": 12
}/getTaskResultтребует clientKeyОтдаёт состояние задачи, а по готовности — объект решения.
{
"clientKey": "YOUR_API_KEY",
"taskId": 12
}{
"errorId": 0,
"status": "ready",
"solution": {
"gRecaptchaResponse": "03AGdBq26...",
"userAgent": "Mozilla/5.0 ..."
}
}/getBalanceтребует clientKeyОтдаёт баланс. Биллинга у продукта нет, поэтому величина постоянная; ноль означает, что лицензия неактивна.
/getQueueStatsключ не требуетсяЗанятость: сколько задач в работе, насколько загружен пул решателя.
/reportIncorrectImageCaptchaтребует clientKeyПринимается для совместимости: обучать на отчётах продукт не умеет.
/reportIncorrectRecaptchaтребует clientKeyТо же самое для RC.
/reportCorrectRecaptchaтребует clientKeyТо же самое для подтверждения верного решения.
/testключ не требуетсяВозвращает разобранное тело запроса. Полезно, когда чужой клиент шлёт не то.
Коды ошибок
Коды и их названия — протокольные: клиентские библиотеки сравнивают именно строку errorCode. Ниже те, которые выдаёт этот сервис.
| errorId | errorCode | Когда |
|---|---|---|
| 1 | ERROR_KEY_DOES_NOT_EXIST | Ключ неверен либо адрес временно заблокирован за подбор. |
| 2 | ERROR_NO_SLOT_AVAILABLE | Свободных решателей нет прямо сейчас либо исчерпан потолок max_concurrent. |
| 10 | ERROR_ZERO_BALANCE | Лицензия неактивна: продлите её, задачи не принимаются. |
| 11 | ERROR_IP_NOT_ALLOWED | Запрос пришёл не с этой машины, а LAN не разрешён — ни общей «Разрешить LAN», ни полем allow_lan. |
| 12 | ERROR_CAPTCHA_UNSOLVABLE | Решить не удалось. Повтор возможен, но профиль останется прежним, пока порт не закроется по простою; если отказ повторяется, проверьте адрес страницы и параметры сайта: ключ, gt, challenge. |
| 16 | ERROR_NO_SUCH_CAPCHA_ID | Задачи с таким taskId нет: она завершилась и была удалена по истечении task_ttl, либо принадлежит другому ключу. |
| 23 | ERROR_TASK_NOT_SUPPORTED | Тип задачи не поддержан, нужная модель не установлена или задача не того вида — например, капча AWS внутри формы (wafType: widget). |
| 25 | ERROR_PROXY_CONNECT_REFUSED | Ваш прокси отверг соединение. Чинить надо прокси, повторять задачу бесполезно. |
| 26 | ERROR_PROXY_CONNECT_TIMEOUT | До вашего прокси не удалось дозвониться за отведённое время. |
| 27 | ERROR_PROXY_READ_TIMEOUT | Ваш прокси принял соединение и замолчал. |
| 49 | ERROR_PROXY_NOT_AUTHORISED | Ваш прокси отверг логин или пароль. |
Границы
- Задачи живут в памяти и перезапуск не переживают: после него taskId прежних задач отвечает ERROR_NO_SUCH_CAPCHA_ID.
- Задача, не завершившаяся за отведённый бюджет, признаётся провалившейся и освобождает место в потолке.
- Обратного вызова нет: поле callbackUrl принимается и игнорируется, результат забирается опросом.
- Задачи на один и тот же сайт с одного прокси выполняются по очереди — это свойство защиты от повторов, а не потолок настроек.