Как решить Cloudflare Turnstile в Node.js и TypeScript

Cloudflare Turnstile встречается в двух формах, и для них нужен разный код. Виджет внутри формы — это вызов с двумя аргументами. Полностраничная промежуточная проверка требует двух дополнительных значений, считанных со страницы, и токен будет принят, только если вы вернёте тот же user agent, который использовал решатель. Именно это последнее требование порождает токены, которые выглядят идеально, но каждый раз не проходят.
Как их различить
| Виджет | Страница проверки | |
|---|---|---|
| Внешний вид | Чекбокс внутри рабочей формы | Полностраничная промежуточная проверка, страница заблокирована |
| Требуются cData и chlPageData | Нет | Да |
| Требуется возвращённый user agent | Нет | Да |
Наш живая демонстрация Turnstile использует вариант с виджетом, что служит полезным ориентиром, когда вы разбираетесь, какой из них перед вами.
Настройка
npm install capskip
const { CapSkip } = require('capskip');
const solver = new CapSkip({
host: '127.0.0.1',
port: 8080,
recaptchaTimeout: 300, // seconds, also covers Turnstile
});CapSkip решает капчу локально, поэтому десктопное приложение должно быть запущено, прежде чем любой вызов сработает.
Режим виджета
const result = await solver.turnstile( '0x4AAAAAAA...', // the data-sitekey attribute 'https://example.com/login', ); console.log(result.code); // cf-turnstile-response token
Поместите result.code в cf-turnstile-response поле и отправьте. Больше ничего не требуется.
Страницам проверки нужны ещё два значения
Промежуточная страница несёт состояние для каждого запроса, к которому привязывается токен. Две его части должны передаваться вместе с решением:
- cData, передаётся как
data - chlPageData, передаётся как
pagedata
Оба находятся на самой странице задания, а не в атрибуте формы, поэтому страницу нужно загрузить, прежде чем её можно будет решить. На стандартной промежуточной странице Cloudflare они лежат в собственном объекте параметров задания страницы’, рядом с sitekey. Они одноразовые и привязаны к этой загрузке страницы, поэтому загружайте и решайте вместе, а не кэшируйте.
const result = await solver.turnstile(sitekey, pageUrl, {
data: cData, // the cData value
pagedata: chlPageData, // the chlPageData value
action: 'managed', // optional, when the page declares one
});
console.log(result.code);
console.log(result.userAgent); // required for the next stepUser agent не является необязательным
Turnstile привязывает токен к браузерному фингерпринту, который его создал, а user agent — часть этого фингерпринта. CapSkip возвращает тот, который он использовал, в result.userAgent. Отправьте токен со стандартным user agent fetch из Node — и Cloudflare отклонит в остальном совершенно корректный токен.
userAgent заполняется только для Turnstile. Для всех остальных типов капчи оно undefined, и именно поэтому это ставит в тупик тех, кто повторно использует рабочий хелпер для reCAPTCHA.
const response = await fetch(pageUrl, {
method: 'POST',
headers: {
// Send back the exact user agent the solve was performed with.
'User-Agent': result.userAgent,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'cf-turnstile-response': result.code,
}),
});Если токен отклоняется, а cData свежий, это почти всегда и есть причина.
TypeScript
import { CapSkip, SolveResult } from 'capskip';
const solver = new CapSkip({ host: '127.0.0.1', port: 8080 });
const result: SolveResult = await solver.turnstile(sitekey, pageUrl);
// userAgent is optional on the type, because only Turnstile populates it.
if (result.userAgent) {
// safe to forward
}Определения поставляются вместе с пакетом, поэтому нет @types установка. Опциональная типизация в userAgent служит полезным напоминанием: компилятор не даст вам забыть, что другие типы капчи оставляют его пустым.
Прокси и параллелизм
// Solve through the same egress you will submit from.
await solver.turnstile(sitekey, pageUrl, {
data: cData,
pagedata: chlPageData,
proxy: { type: 'HTTPS', uri: 'user:[email protected]:3128' },
});
// Several at once.
const results = await Promise.all(targets.map((t) =>
solver.turnstile(t.sitekey, t.url)));Прокси работают для Turnstile, reCAPTCHA и GeeTest, но не для картиночных капч, которые никогда не касаются целевого сайта. Для страниц с задачами каждому решению нужен свой свежеполученный cData, поэтому получайте его внутри маппированной функции, а не пакетом заранее.
Часто задаваемые вопросы
Нужен ли виджетам когда-либо cData?
Нет, и передача пустых значений скорее приведёт к сбою решения, чем поможет. Их используют только полностраничные промежуточные задачи.
Токен выглядит нормально, но сайт его отклоняет.
Почти всегда это user agent. Отправляйте, используя result.userAgent вместо того, что ваш HTTP-клиент отправляет по умолчанию. Вторая наиболее вероятная причина — устаревший cData, который привязан к одной загрузке страницы.
Можно ли использовать это с Puppeteer?
Да, и это хорошо сочетается: считайте cData с загруженной страницы с помощью page.evaluate, решите с помощью этого SDK, затем установите тот же user agent на странице, прежде чем продолжить. Наш Сервис распознавания капчи для Node.js страница охватывает сторону автоматизации.
Сводка
Виджеты принимают sitekey и URL. Страницам заданий нужен data и pagedata считывается заново со страницы, и токен должен быть отправлен вместе с result.userAgent. Всё остальное — обычная работа с Promise.
Другие языки — на Сервис распознавания Cloudflare Turnstile странице, детали параметров в Документация по API, а более широкий набор возможностей Node — на Сервис распознавания капчи для Node.js странице. CapSkip является безлимитный сервис распознавания капчи который работает на вашем оборудовании.
