npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@itd-api/turnstile

v0.1.0

Published

Получение токена Cloudflare Turnstile для входа в itd-api через локальный браузер

Downloads

467

Readme

@itd-api/turnstile

Токен Cloudflare Turnstile для входа по логину и паролю в itd-api.

Руководство · API из TSDoc

Вход на итд.com требует токен капчи, а получить его можно только в браузере. Этот пакет поднимает браузер, берёт токен и отдаёт функцию, которая подставляется в auth клиента.

Отдельным пакетом — чтобы itd-api оставался клиентом API: без Playwright в зависимостях, без требования графической оболочки и без кода, который нужен далеко не всем.

Когда пакет не нужен

Капча участвует только в самом входе по паролю — ни продление сессии, ни обычные запросы, ни realtime её не требуют. Пакет незачем ставить, если:

  • сессия уже сохранена в FileTokenStorage — клиент продлевает её сам;
  • токены можно скопировать из браузера, где вы уже вошли: DevTools отдают и access token, и cookie refresh_token;
  • токен выдаёт ваш backend или secret manager — тогда подойдёт auth: { getToken };
  • токен капчи приходит из своего источника — getTurnstileToken принимает любую функцию.

Пакет нужен ровно для одного сценария: полностью автоматический вход по email и паролю в Node без участия человека.

Установка

npm i @itd-api/turnstile patchright
npx patchright install chromium

Драйвер подключается динамически, в порядке patchrightplaywrightplaywright-core: что из этого установлено, то и берётся. Все три — необязательные одноранговые зависимости, достаточно любой одной. Любой другой совместимый по API драйвер передаётся через launch. Какие связки сейчас выдают токен — в разделе Совместимость.

Использование

import { ItdClient } from 'itd-api';
import { FileTokenStorage } from 'itd-api/node';
import { createTurnstileSolver } from '@itd-api/turnstile';

const itd = new ItdClient({
  storage: new FileTokenStorage('./.itd-session.json'),
  auth: {
    email: process.env.ITD_EMAIL!,
    password: process.env.ITD_PASSWORD!,
    getTurnstileToken: createTurnstileSolver(),
  },
});

Передаётся именно функция: токен одноразовый и живёт несколько минут, поэтому клиент спрашивает его заново перед каждым входом. Браузер поднимается на время одного вызова и сразу закрывается.

Разовый вызов без клиента:

import { solveTurnstile } from '@itd-api/turnstile';

const token = await solveTurnstile();

Запуск на сервере

Браузер по умолчанию запускается с окном. В безоконном режиме виджет проходится заметно хуже: признаки такого режима видны странице. На сервере без графической оболочки поднимите виртуальный дисплей — это надёжнее, чем headless: true:

apt install xvfb
xvfb-run -a node bot.js

В Docker к образу нужны системные библиотеки браузера: npx patchright install --with-deps chromium.

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

Пакет не заходит на сайт. Навигация на https://xn--d1ah4a.com/ перехватывается и вместо настоящей страницы отдаётся своя — с одним виджетом Turnstile. Для браузера origin при этом настоящий, поэтому привязка ключа к домену не нарушается, а сервер при проверке токена видит ожидаемый hostname.

Из этого следует остальное:

  • пароль в браузер не попадает — форма входа не участвует, вход выполняет сам itd-api;
  • ничего не ломается от изменений вёрстки сайта: важен только публичный ключ виджета;
  • нет гонки с настоящим запросом входа, а значит и незачем его подвешивать.

Чекбокс живёт в iframe чужого происхождения, до его DOM не дотянуться — клик идёт по координатам. Отсчёт ведётся от собственного контейнера известного размера, поэтому попадание не зависит от чужой вёрстки. Координаты слегка разбрасываются, первому касанию предшествует пауза, а User-Agent не подменяется: заявленная версия, разошедшаяся с реальным движком, сама по себе служит признаком автоматизации.

Настройки

Все необязательны.

| Параметр | По умолчанию | Что делает | | --- | --- | --- | | headless | false | Запуск без окна. См. раздел про сервер. | | disableSandbox | false | Отключить sandbox Chromium; только для изолированного контейнера. | | timeout | 60000 | Сколько ждать токен, мс. | | attempts | 2 | Сколько попыток при таймауте. | | theme | 'auto' | Оформление виджета. | | origin | https://xn--d1ah4a.com | Сайт, чей виджет решается. | | sitekey | ключ итд.com | Публичный ключ виджета. | | driver | перебор | Какой драйвер брать, когда установлено несколько. | | executablePath | — | Путь к браузеру, если он лежит не там, где его ищет драйвер. | | channel | — | Канал браузера, например chrome, вместо сборки из комплекта драйвера. | | args | — | Дополнительные аргументы командной строки. | | proxy | — | Прокси для браузера. | | browser | — | Готовый браузер. Тогда пакет его не запускает и не закрывает. | | launch | — | Свой запуск браузера. Заменяет все параметры запуска. | | contextOptions | locale: 'ru-RU', окно 1280×800 | Настройки контекста. Заменяют стандартные целиком. | | logger | — | Куда писать ход решения, например console.debug. |

Свой драйвер:

createTurnstileSolver({
  launch: async () => {
    const { chromium } = await import('patchright');
    return chromium.launch({ headless: false });
  },
});

Драйверу, который собирает отпечаток браузера сам, контекст лучше отдать целиком:

createTurnstileSolver({
  contextOptions: {},
  launch: async () => {
    const { Camoufox } = await import('camoufox-js');
    return Camoufox({ headless: false, humanize: true });
  },
});

Ошибки

Всё, что пошло не так, приходит как TurnstileError с полем reason:

| reason | Что делать | | --- | --- | | driver-missing | Установить patchright либо передать свой launch. | | launch-failed | Браузер не запустился: нет исполняемого файла или дисплея. | | timeout | Виджет не отдал токен. Обычно лечится повтором. | | widget-error | Виджет отказал; код Cloudflare лежит в widgetCode. |

Код 110200 в widgetCode означает, что ключ не разрешён для указанного домена, — повторять бессмысленно, и пакет этого не делает.

Совместимость

Виджет пропускает не всякий браузер. Данные на 5 августа 2026 года:

| Драйвер | Версии | Браузер | Токен | | --- | --- | --- | --- | | patchright | 1.59.4, 1.60.2, 1.61.1 | Chromium 147, 148, 149 | ✅ | | playwright | 1.60.0, 1.61.0 | Chromium 148, 149 | ✅ | | playwright | 1.62.1 | Chromium 151 | ❌ | | playwright с channel: 'chrome' | 1.61.0 | Google Chrome 150 | ❌ | | camoufox-js с contextOptions: {} | 0.11.5, 0.12.0 | Camoufox 152 | ✅ | | camoufox-js с contextOptions: {} | 0.10.2 | Camoufox 152 | ❌ | | rebrowser-playwright | 1.48.2, 1.49.1, 1.52.0 | Chromium 149 | ❌ | | playwright-extra + puppeteer-extra-plugin-stealth 2.11 | 4.3.4, 4.3.5, 4.3.6 | Chromium 149 | ❌ |

Всё перечисленное — с окном; headless: true токена не даёт нигде, кроме Camoufox. Двум последним сборка задана принудительно, чтобы отказ относился к самой библиотеке.

Сборка приезжает вместе с версией драйвера, ею и выбирается — npm i [email protected]. Поставленная отдельно тоже годится: npx @puppeteer/browsers install [email protected] и путь в executablePath. Версию запущенного браузера пакет называет в сообщении о таймауте.

Таблица пересобирается скриптом scripts/drivers.mjs из исходников пакета:

npm i --no-save patchright playwright camoufox-js
node scripts/drivers.mjs

Лицензия

MIT