@itd-api/captcha
Получает токены собственной капчи ИТД и Cloudflare Turnstile для входа через itd-api. Сервер принимает обе: виджет выбираете вы либо он сам.
Пакет запускает браузер, решает виджет выбранного типа, возвращает токен и закрывает браузер.
Когда пакет не нужен
Капча участвует во входе по паролю, регистрации, сбросе пароля и подтверждении QR-входа — ни продление сессии, ни обычные запросы, ни событийные соединения её не требуют. Пакет незачем ставить, если:
- сессия уже сохранена в
FileTokenStorage— клиент продлевает её сам; - токены можно скопировать из браузера, где вы уже вошли: DevTools отдают и access token, и cookie
refresh_token; - access token выдаёт серверное приложение или хранилище секретов — тогда подойдёт
auth: { getToken }; - токен капчи приходит из своего источника — опция клиента
captchaпринимает любую функцию.
Установка
npm i @itd-api/captcha patchright
npx patchright install chromiumДрайвер подключается динамически, в порядке patchright → playwright → playwright-core: что из этого установлено, то и берётся. Все три — необязательные одноранговые зависимости, достаточно любой одной. Любой другой совместимый по API драйвер передаётся через launch. Какие связки сейчас выдают токен — в разделе Совместимость.
Использование
import { ItdClient } from 'itd-api';
import { FileTokenStorage } from 'itd-api/node';
import { createCaptchaSolver } from '@itd-api/captcha';
const itd = new ItdClient({
storage: new FileTokenStorage('./.itd-session.json'),
auth: { email: process.env.ITD_EMAIL!, password: process.env.ITD_PASSWORD! },
captcha: createCaptchaSolver(),
});Клиент спрашивает токен каждый раз, когда сервер требует капчу; браузер поднимается на время одного вызова и сразу закрывается. Тот же источник, заданный контейнеру ItdAccounts, достаётся каждому аккаунту.
Какую капчу проходить
Сервер принимает обе. Без настройки источник следует за сервером: клиент спрашивает активного провайдера и просит пройти именно его виджет, так что переключение провайдера переживается без правок кода.
Нужен конкретный виджет — назовите его, и лишнего запроса к серверу не будет:
import { createCaptchaSolver, CaptchaType } from '@itd-api/captcha';
createCaptchaSolver({ type: CaptchaType.Cloudflare }); // всегда Turnstile
createCaptchaSolver({ type: CaptchaType.Itd }); // всегда капча ИТДНезнакомый тип отвергается при создании, а не в момент входа.
Имя поля, в котором сервер ждёт токен, клиент при закреплённом типе берёт из своей таблицы. Если сервер его переименовал, назовите поле сами: createCaptchaSolver({ type, field: 'c7f2' }).
Один токен без клиента
import { solveCaptcha, CaptchaType } from '@itd-api/captcha';
const token = await solveCaptcha(CaptchaType.Itd);Запуск на сервере
Браузер по умолчанию запускается с окном. В безоконном режиме виджет проходится заметно хуже: признаки такого режима видны странице. На сервере без графической оболочки поднимите виртуальный дисплей — это надёжнее, чем headless: true:
apt install xvfb
xvfb-run -a node bot.jsВ Docker к образу нужны системные библиотеки браузера: npx patchright install --with-deps chromium.
Как это устроено
Пакет не заходит на сайт. Навигация на https://xn--d1ah4a.com/ перехватывается и вместо настоящей страницы отдаётся своя — с одним виджетом. Домен остаётся настоящим, поэтому привязка ключа не нарушается, а сервер видит ожидаемое имя хоста.
Из этого следует остальное:
- пароль в браузер не попадает — форма входа не участвует, вход выполняет сам
itd-api; - ничего не ломается от изменений вёрстки сайта: важен только публичный ключ виджета;
- нет гонки с настоящим запросом входа, а значит и незачем его подвешивать.
Чекбокс живёт в iframe чужого происхождения, до его DOM не дотянуться — клик идёт по координатам. Отсчёт ведётся от собственного контейнера известного размера, поэтому попадание не зависит от чужой вёрстки. Координаты слегка разбрасываются, первому касанию предшествует пауза, а User-Agent не подменяется: заявленная версия, разошедшаяся с реальным движком, сама по себе служит признаком автоматизации.
Капча ИТД оценивает и поведение указателя, поэтому клик идёт настоящей мышью браузера (через CDP), а не программной установкой значения, — то же движение курсора, что и у человека.
Настройки
Все необязательны.
| Параметр | По умолчанию | Что делает |
|---|---|---|
headless | false | Запуск без окна. См. раздел про сервер. |
disableSandbox | false | Отключить sandbox Chromium; только для изолированного контейнера. |
timeout | 60000 | Сколько ждать токен, мс. |
attempts | 2 | Сколько попыток при таймауте. |
theme | 'auto' | Оформление виджета. |
origin | https://xn--d1ah4a.com | Сайт, чей виджет решается. |
driver | перебор | Какой драйвер брать, когда установлено несколько. |
executablePath | — | Путь к браузеру, если он лежит не там, где его ищет драйвер. |
channel | — | Канал браузера, например chrome, вместо сборки из комплекта драйвера. |
args | — | Дополнительные аргументы командной строки. |
proxy | — | Прокси для браузера. |
browser | — | Готовый браузер. Тогда пакет его не запускает и не закрывает. |
launch | — | Свой запуск браузера. Заменяет все параметры запуска. |
contextOptions | locale: 'ru-RU', окно 1280×800 | Настройки контекста. Заменяют стандартные целиком. |
logger | — | Функция для вывода хода решения, например console.debug. |
type | — | Какую капчу проходить всегда. Только для createCaptchaSolver. |
field | — | Поле тела запроса для закреплённого типа. Только вместе с type. |
createCaptchaSolver({ type: CaptchaType.Itd, timeout: 90_000, headless: true });Свой драйвер:
createCaptchaSolver({
launch: async () => {
const { chromium } = await import('patchright');
return chromium.launch({ headless: false });
},
});Драйверу, который собирает отпечаток браузера сам, контекст лучше отдать целиком:
createCaptchaSolver({
contextOptions: {},
launch: async () => {
const { Camoufox } = await import('camoufox-js');
return Camoufox({ headless: false, humanize: true });
},
});Ошибки
Всё, что пошло не так, приходит как CaptchaError с полем reason (и type, когда виджет уже выбран):
reason | Что делать |
|---|---|
driver-missing | Установить patchright либо передать свой launch. |
launch-failed | Браузер не запустился: нет исполняемого файла или дисплея. |
browser-closed | Окно закрыли или процесс браузера завершился до получения токена. |
timeout | Виджет не отдал токен. Обычно лечится повтором. |
widget-error | Виджет отказал; для Cloudflare код лежит в widgetCode. |
Код 110200 в widgetCode означает, что ключ Turnstile не разрешён для указанного домена, — повторять бессмысленно, и пакет этого не делает.
Совместимость
Таблица ниже показывает выдачу токена Cloudflare Turnstile на разных версиях драйверов и браузеров.
| Драйвер | Версия и конфигурация | Браузер | Turnstile | Проверено |
|---|---|---|---|---|
patchright | 1.62.2, штатная сборка | Chromium 151 | ✕ Нет | 02.09.2026 |
1.62.2, executablePath | Chromium 148 · 149 | ✓ Работает | 02.09.2026 | |
| 1.59.4 · 1.60.2 · 1.61.1, штатные сборки | Chromium 147 · 148 · 149 | ✓ Работает | 05.08.2026 | |
playwright | 1.62.1, штатная сборка | Chromium 151 | ✕ Нет | 02.09.2026 |
1.62.1, executablePath | Chromium 148 · 149 | ✓ Работает | 02.09.2026 | |
| 1.60.0 · 1.61.0, штатные сборки | Chromium 148 · 149 | ✓ Работает | 05.08.2026 | |
playwright-core | 1.62.1, executablePath | Chromium 149 | ✓ Работает | 02.09.2026 |
camoufox-js | 0.12.0, playwright-core 1.60.0, contextOptions: {} | Camoufox 152.0.4-beta.29 | ✓ С окном и headless | 02.09.2026 |
0.11.5, contextOptions: {} | Camoufox 152 | ✓ Работает | 05.08.2026 | |
rebrowser-playwright | 1.48.2 · 1.49.1 · 1.52.0, executablePath | Chromium 149 | ✕ Нет | 02.09.2026 |
playwright-extra + puppeteer-extra-plugin-stealth | 4.3.6 + 2.11.2, playwright 1.62.1, executablePath | Chromium 149 | ✕ Нет | 02.09.2026 |
Собственная капча ИТД менее требовательна: ее можно получить любым подходящим драйвером и версией браузера.
Таблица проверяется скриптом scripts/drivers.mjs из исходников пакета:
npm i --no-save patchright playwright camoufox-js
node scripts/drivers.mjs # Turnstile
node scripts/drivers.mjs --itd # капча ИТДШтатная сборка приезжает вместе с версией драйвера. Другую можно поставить командой npx @puppeteer/browsers install chrome@149.0.7827.55 и передать путь в executablePath. Версия драйвера сама по себе не гарантирует результат: например, playwright 1.62.1 не проходит Turnstile на штатном Chromium 151, но проходит на Chromium 148 и 149.