API — Распознавание капч

Отдельный слушатель, говорящий на протоколе anti-captcha.com: направьте на него стороннее ПО и решайте картинки, куки доступа и reCAPTCHA v2 через свои прокси.

Что это

BlankTrail Proxy умеет принимать задачи на распознавание капч по протоколу anti-captcha.com. Это отдельный слушатель на своём порту: стороннее ПО, уже умеющее работать с этим протоколом, достаточно направить на ваш адрес вместо адреса сервиса распознавания.

Слушатель отдельный, а не маршруты на порту панели, по двум причинам. Официальные клиенты протокола бьют в корень хоста, то есть занимают корневые пути целиком. И капча-API вполне может понадобиться в локальной сети там, где панель управления не должна быть видна никому.

По умолчанию выключенКапча-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Адрес слушателя. Пустой хост означает петлю, пока не включён allow_lan.
allow_lanПринимать ли запросы не с этой машины. Настройка своя, отдельная от такой же у панели; в образе 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
Почему allow_lan в образе включёнВ контейнере запрос приходит с адреса моста Docker, а не с петли: с выключенным allow_lan пустой хост :8892 подставился бы на 127.0.0.1, и проброшенный порт отвечал бы отказом в соединении. Общий BT_ALLOW_LAN на капча-API по-прежнему не действует, а BT_CAPTCHA_API_ALLOW_LAN нужен только со своим конфигом вместо образного.

Ключ и доступ

clientKey — это ключ API вашей панели, тот же самый. Отдельного ключа для капча-API нет: заводить вторую тайну с собственным хранением и ротацией ради одной поверхности незачем.

  • Ключ приезжает в ТЕЛЕ запроса, как того требует протокол, а не в заголовке.
  • Подбор ключа ограничивается: после серии неудач адрес получает отказ независимо от того, верен ли следующий ключ.
  • Запросы не с этой машины отвергаются, пока не включён allow_lan, — включая getQueueStats и test.

Поддерживаемые типы задач

ТипЧто делает
ImageToTextTaskРаспознаёт текст на картинке локальной моделью.
AntiGateTaskПроходит защиту сайта и возвращает куки доступа.
RecaptchaV2TaskРешает reCAPTCHA v2 по адресу страницы и ключу сайта, через ваш прокси.
RecaptchaV2TaskProxylessТо же самое, но без вашего прокси — выход прямой.

Прочие типы протокола отвечают ERROR_TASK_NOT_SUPPORTED. Это штатный ответ, а не сбой: клиент видит его сразу при создании задачи и может уйти к другому сервису, не тратя ожидания.

Как устроена работа

  1. Создаёте задачу через createTask и получаете числовой taskId.
  2. Опрашиваете getTaskResult, пока в ответе стоит processing.
  3. Получаете ready и объект решения — его состав зависит от типа задачи.
Ответ всегда HTTP 200Ошибка сообщается полями errorId и errorCode в теле, а не кодом HTTP — так устроен протокол. Клиент, увидевший не-200, счёл бы сервис упавшим и ушёл бы в свои повторы.

Распознавание картинки

Картинка передаётся в base64. Ответ несёт распознанный текст в поле text.

{
  "clientKey": "YOUR_API_KEY",
  "task": {
    "type": "ImageToTextTask",
    "body": "iVBORw0KGgoAAAANSUhEUg..."
  }
}
Модель обучена на своёмЧиталка обучалась на текстовых капчах Google. На капче другой рисовки точность заметно ниже, и это свойство модели, а не настройка: проверьте долю верных ответов на своём материале, прежде чем строить на ней процесс.

Куки доступа

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"
  }
}
Куки работают только через названный портВ решении есть поле fingerprint с адресом blanktrail.replayProxy. Куки доступа привязаны к паре «выход плюс отпечаток», и предъявленные с другого адреса или из другого клиента они будут отвергнуты сайтом. Направьте свой запрос через этот порт — он уже открыт под ваш прокси и живёт до простоя, заданного port_idle_timeout.

reCAPTCHA v2

Задаче нужны адрес страницы и публичный ключ сайта. Вариант без вашего прокси называется 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
  }
}

Что происходит с присланным userAgent

Присланный userAgent не уезжает на провод. Он ВЫБИРАЕТ ближайший профиль по семейству браузера, мажорной версии и операционной системе, а на провод идёт user-agent этого профиля — вместе с согласованными с ним отпечатками TLS и HTTP/2.

Используйте userAgent из ответаВ решении поле userAgent содержит ФАКТИЧЕСКИЙ user-agent, под которым добыт токен. Подставьте в свой запрос именно его. Чужой заголовок поверх нашего провода — это ровно то расхождение, которое продукт устраняет: выдав его, капча-API стал бы источником примет вместо их сокрытия.

Методы

POST/createTaskтребует clientKey

Создаёт задачу и возвращает числовой taskId.

Ответ
{
  "errorId": 0,
  "taskId": 12
}
POST/getTaskResultтребует clientKey

Отдаёт состояние задачи, а по готовности — объект решения.

Запрос
{
  "clientKey": "YOUR_API_KEY",
  "taskId": 12
}
Ответ
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "gRecaptchaResponse": "03AGdBq26...",
    "userAgent": "Mozilla/5.0 ..."
  }
}
POST/getBalanceтребует clientKey

Отдаёт баланс. Биллинга у продукта нет, поэтому величина постоянная; ноль означает, что лицензия неактивна.

POST/getQueueStatsключ не требуется

Занятость: сколько задач в работе, насколько загружен пул решателя.

POST/reportIncorrectImageCaptchaтребует clientKey

Принимается для совместимости: обучать на отчётах продукт не умеет.

POST/reportIncorrectRecaptchaтребует clientKey

То же самое для reCAPTCHA.

POST/reportCorrectRecaptchaтребует clientKey

То же самое для подтверждения верного решения.

POST/testключ не требуется

Возвращает разобранное тело запроса. Полезно, когда чужой клиент шлёт не то.

Коды ошибок

Коды и их названия — протокольные: клиентские библиотеки сравнивают именно строку errorCode. Ниже те, которые выдаёт этот сервис.

errorIderrorCodeКогда
1ERROR_KEY_DOES_NOT_EXISTКлюч неверен либо адрес временно заблокирован за подбор.
2ERROR_NO_SLOT_AVAILABLEСвободных решателей нет прямо сейчас либо исчерпан потолок max_concurrent.
10ERROR_ZERO_BALANCEЛицензия неактивна: продлите её, задачи не принимаются.
11ERROR_IP_NOT_ALLOWEDЗапрос пришёл не с этой машины, а allow_lan выключен.
12ERROR_CAPTCHA_UNSOLVABLEРешить не удалось. Повтор возможен, но профиль останется прежним, пока порт не закроется по простою; если отказ повторяется, проверьте адрес страницы и ключ сайта.
16ERROR_NO_SUCH_CAPCHA_IDЗадачи с таким taskId нет: она завершилась и была удалена по истечении task_ttl, либо принадлежит другому ключу.
23ERROR_TASK_NOT_SUPPORTEDТип задачи не поддержан либо нужная модель не установлена.
25ERROR_PROXY_CONNECT_REFUSEDВаш прокси отверг соединение. Чинить надо прокси, повторять задачу бесполезно.
26ERROR_PROXY_CONNECT_TIMEOUTДо вашего прокси не удалось дозвониться за отведённое время.
27ERROR_PROXY_READ_TIMEOUTВаш прокси принял соединение и замолчал.
49ERROR_PROXY_NOT_AUTHORISEDВаш прокси отверг логин или пароль.
Коды про прокси называют ВАШ проксиЧетыре кода 25, 26, 27 и 49 относятся к прокси, который вы прислали в задаче, а не к нашему выходу. Если прокси отвечает исправно, а решить не удалось, вы получите ERROR_CAPTCHA_UNSOLVABLE: свою неудачу мы на ваш прокси не списываем.

Границы

  • Задачи живут в памяти и перезапуск не переживают: после него taskId прежних задач отвечает ERROR_NO_SUCH_CAPCHA_ID.
  • Задача, не завершившаяся за отведённый бюджет, признаётся провалившейся и освобождает место в потолке.
  • Обратного вызова нет: поле callbackUrl принимается и игнорируется, результат забирается опросом.
  • Задачи на один и тот же сайт с одного прокси выполняются по очереди — это свойство защиты от повторов, а не потолок настроек.

Что дальше