Перейти к основному содержимому
Возникают проблемы с получением токена?
Свяжитесь с поддержкой

TurnstileTask | Cloudflare Challenge

Автоматически поддерживаются все подтипы Turnstile: manual, non-interactive и invisible. Поэтому нет необходимости указывать подтип для обычной капчи.

Ещё больше по теме в нашем блоге
Ещё больше по теме в нашем блоге
Внимание!

Ознакомьтесь со всеми тремя вариантами распознавания капчи и выберете наиболее предпочтительный для вас.

Вариант 1 (Turnstile)

Вам требуется решить обычную turstile капчу, как здесь. Обратите внимание, что капча на страницах CloudFlare может выглядеть идентично. Посмотрите в конце статьи как отличить обычный Turnstile от Cloudflare Challenge.

Параметры запроса

type<string>required

TurnstileTaskProxyless


websiteURL<string>required

Адрес страницы, на которой решается капча


websiteKey<string>required

Ключ Turnstile


pageAction<string>optional

Поле action, которое можно найти в callback функции для загрузки капчи


data<string>optional

Значение поля data можно взять из параметра cData.

Вариант 2 (CloudFlare)

Вы работаете через браузер, и Вам требуется получить токен для прохождения CloudFlare

Параметры запроса

type<string>required

TurnstileTaskProxyless


websiteURL<string>required

Адрес страницы, на которой решается капча


websiteKey<string>required

Ключ Turnstile


cloudflareTaskType<string>required

token


pageAction<string>required

Поле action, которое можно найти в callback функции для загрузки капчи. Если используется cloudflareTaskType, то action обычно “managed“ или “non-interactive“.


userAgent<string>required

User-Agent браузера.
Передавайте только актуальный UA от ОС Windows. Сейчас таковым является: userAgentPlaceholder


data<string>required

Значение поля data можно взять из параметра cData.


pageData<string>required

Значение поля pageData можно взять из параметра chlPageData.


apiJsUrl<string>optional

Строка, которая содержит ссылку на скрипт капчи.


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

Эти параметры находятся в объекте, который передаётся во время создания капчи в функцию window.turnstile.render(el, paramsObj). Получить их можно, например, с помощью выполнения JavaScript перед загрузкой остальных скриптов:

(function () {
const obj = {
render: function () {
const { action, cData, chlPageData } = arguments[1];
const params = [
["action", action],
["data", cData],
["pageData", chlPageData],
];
console.table(params)
}
};

Object.defineProperty(window, "turnstile", {
get: () => {
return obj;
},
});
})();

При вызове window.turnstile.render(el, paramsObj) загружается капча на странице, и при успешном решении вызывается функция callback, которая передает информацию о решении.

window.turnstile.render(el, paramsObj):

el: DOM-элемент для вставки в него капчи.

paramsObj: Объект параметров, содержащий информацию о капче и инструкции для ее решения. Этот объект обычно содержит такие поля, как sitekey, action, cData, chlPageData, callback.

callback – функция обратного вызова после успешного прохождения капчи.

Вариант 3 (CloudFlare)

Вы работаете с помощью запросов, и Вам требуются куки cf_clearance. Обязательно нужны ваши прокси

Параметры запроса

type<string>required

TurnstileTask


websiteURL<string>required

Адрес страницы, на которой решается капча


websiteKey<string>required

Ключ Turnstile(можно передать любую строку)


cloudflareTaskType<string>optional

cf_clearance


htmlPageBase64<string>required

Закодированная в base64 html страница "Just a moment", которая выдаётся с кодом 403 при обращении к сайту с данной защитой.
Пример получения строки htmlPageBase64:
var htmlContent = document.documentElement.outerHTML;
var htmlBase64 = btoa(unescape(encodeURIComponent(htmlContent)));
console.log(htmlBase64);


userAgent<string>required

User-Agent браузера.
Передавайте только актуальный UA от ОС Windows. Сейчас таковым является версия: userAgentPlaceholder


proxyType<string>required

http - regular http/https proxy;
https - try this option only if "http" doesn't work (required for some custom proxies);
socks4 - socks4 proxy;
socks5 - socks5 proxy.


proxyAddress<string>required

IP адрес прокси IPv4/IPv6. Не допускается:

  • использование имен хостов;
  • использование прозрачных прокси (там, где можно видеть IP клиента);
  • использование прокси на локальных машинах.


proxyPort<integer>required

Порт прокси.


proxyLogin<string>required

Логин прокси-сервера.


proxyPassword<string>required

Пароль прокси-сервера.

Примеры запросов

Вариант 1. Обычный Turnstile:

POST
https://api.capmonster.cloud/createTask

Запрос

{
"clientKey":"API_KEY",
"task":
{
"type":"TurnstileTaskProxyless",
"websiteURL":"http://tsmanaged.zlsupport.com",
"websiteKey":"0x4AAAAAAABUYP0XeMJF0xoy"
}
}

Ответ

{
"errorId":0,
"taskId":407533072
}

Вариант 2. CloudFlare (token)

POST
https://api.capmonster.cloud/createTask

Запрос

{
"clientKey": "API_KEY",
"task": {
"type": "TurnstileTask",
"websiteURL": "https://example.com",
"websiteKey": "0x4AAAAAAADnPIDROrmt1Wwj",
"cloudflareTaskType": "token",
"userAgent":"userAgentPlaceholder",
"pageAction": "managed",
"pageData": "HUHDWUHuhuwfiweh32..uh2uhuhyugYUG=",
"data": "874291f4retD1366"
}
}

Ответ

{
"errorId":0,
"taskId":407533072
}
POST
https://api.capmonster.cloud/createTask

Запрос

{
"clientKey":"API_KEY",
"task": {
"type":"TurnstileTask",
"websiteURL":"https://example.com",
"websiteKey":"xxxxxxxxxx",
"cloudflareTaskType": "cf_clearance",
"htmlPageBase64": "PCFET0NUWVBFIGh0...vYm9keT48L2h0bWw+",
"userAgent": "userAgentPlaceholder",
"proxyType":"http",
"proxyAddress":"8.8.8.8",
"proxyPort":8080,
"proxyLogin":"proxyLoginHere",
"proxyPassword":"proxyPasswordHere"
}
}

Ответ

{
"errorId":0,
"taskId":407533072
}

Метод получения результата задачи

Используйте метод getTaskResult, чтобы получить решение Turnstile. В зависимости от загрузки системы вы получите ответ через время в диапазоне от 5 до 20 с.

СвойствоТипОписание
cf_clearanceStringСпециальные куки cloudflare, которые вы можете подставить в свой браузер
tokenStringИспользуйте токен при вызове callback функции

Как отличить обычный Turnstile от Cloudflare Challenge.

Cloudflare challenge может выглядеть по-разному.

Обычный вариант:

Стилизованные варианты:

Челлендж органично встроен в сам сайт

Выглядит как обычная капча turnstile, но на самом деле это challenge

Чтобы окончательно убедиться в наличии Cloudflare, можно открыть инструменты разработчика, посмотреть трафик, изучить код страницы и увидеть характерные признаки:

  • Первый запрос к сайту возвращает код 403:

  • Форма с id challenge-form имеет атрибут action (не путать с action из параметров для капчи turnstile), содержащий параметр __cf_chl_f_tk=:

  • На странице находится два похожих тега <script>, которые создают новое значение в объекте window:

Пример реализации решения с помощью Selenium на Node.js

const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

(async function example() {
const options = new chrome.Options();
options.addArguments('--auto-open-devtools-for-tabs')

const driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();

try {
driver.executeScript(`
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === 'render') {
return function(a, b) {
let p = {
type: "TurnstileTaskProxyless",
websiteKey: b.sitekey,
websiteURL: window.location.href,
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent
}

console.log(JSON.stringify(p))
window.params = p;
window.turnstileCallback = b.callback;
return target.render.apply(this, arguments);
}
}
return target[prop];
}
});
`)

driver.get('SITE WITH CAPTCHA');


const params = await driver.executeScript(`
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(window.params)
}, 2000)
})
`);

if (params) {
const data = {
clientKey: 'API KEY',
task: {
type: 'TurnstileTaskProxyless',
websiteURL: params.websiteURL,
websiteKey: params.websiteKey,
data: params.data,
action: params.action
}
}

const createResult = await fetch('https://api.capmonster.cloud/createTask', {
method: 'post',
body: JSON.stringify(data)
});

const createTaskResult = await createResult.json()

if (createTaskResult.taskId) {
const asyncDelay = (timeout) =>
new Promise(resolve => {
setTimeout(() => {
resolve();
}, timeout);
});

const getTaskResult = async (taskId) => {
const taskResult = await fetch('https://api.capmonster.cloud/getTaskResult', {
method: 'post',
body: JSON.stringify({
"clientKey":"API KEY",
"taskId": createTaskResult.taskId
})
});
const taskResponse = await taskResult.json();
if (taskResponse.status === 'processing') {
await asyncDelay(5000);
return await getTaskResult(taskId)
}
return taskResponse;
}

const taskRes = await getTaskResult(createTaskResult.taskId)

if (taskRes.solution) {
await driver.executeScript(`
window.turnstileCallback(${taskRes.solution.token});
`);
}
}

}

//DO SOMETHING
} finally {
await driver.quit();
}
})();

Как найти все нужные параметры для создания задачи на решение

Вручную

  1. Откройте ваш сайт, где отображается капча, в браузере.
  2. Правой кнопкой кликните по элементу капчи и выберите Inspect.

Вариант 1.

websiteKey

Можно найти в Элементах:

sitekeyTurnstile

sitekeyTurnstile1

Также можно использовать команду в консоли, открыв url капчи, начинающегося с: https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/g… в отдельной вкладке:

console.log(window._cf_chl_opt.chlApiSitekey);

chlApiSitekey – это и есть sitekey.

pageAction

Action и также sitekey можно найти в callback-функции:

callbackTurnstile

Параметры для вариантов 2 и 3 лучше извлекать автоматически:

Автоматически

Удобный способ автоматизировать поиск всех необходимых параметров. Некоторые параметры генерируются заново при каждой загрузке страницы, поэтому для их извлечения потребуется работать через браузер – обычный или в режиме headless (например, с помощью Playwright). Так как значения динамических параметров хранятся недолго, капчу нужно решать сразу после их получения.

Важно!

Приведённые фрагменты кода являются базовыми примерами для ознакомления в извлечении необходимых параметров. Точная реализация будет зависеть от вашего сайта с капчей, его структуры и используемых HTML-элементов и селекторов.

Вариант 1 (в браузере)
// Функция для проверки наличия window.onloadTurnstileCallback
const checkTurnstileCallback = () => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject('Таймаут ожидания callback'), 30000);

const interval = setInterval(() => {
if (window.onloadTurnstileCallback !== undefined) {
clearInterval(interval);
clearTimeout(timeout);

const callbackDetails = window.onloadTurnstileCallback.toString();
const sitekeyMatch = callbackDetails.match(/sitekey: ['"]([^'"]+)['"]/);
const actionMatch = callbackDetails.match(/action: ['"]([^'"]+)['"]/);

resolve({
sitekey: sitekeyMatch ? sitekeyMatch[1] : null,
action: actionMatch ? actionMatch[1] : null,
});
}
}, 500);
});
};

// Попытка найти любой элемент с data-sitekey
const turnstileElement = document.querySelector('[data-sitekey]');

if (turnstileElement) {
const sitekey = turnstileElement.getAttribute("data-sitekey");
console.log("Turnstile Sitekey (из элемента):", sitekey);
} else {
console.log("Turnstile элемент не найден. Проверяем через callback...");

checkTurnstileCallback()
.then((data) => {
console.log("Turnstile Params (из callback):", data);
})
.catch((error) => {
console.error(error);
});
}
Вариант 2 (Node.js)
import { chromium } from "playwright";

(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();

let params = null;

try {
while (!params) {
await page.goto("https://example.com");

await page.evaluate(() => {
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === "render") {
return function (a, b) {
const p = {
websiteKey: b.sitekey,
websiteURL: window.location.href,
data: b.cData,
pagedata: b.chlPageData,
action: b.action,
userAgent: navigator.userAgent,
};
window.params = p;
return target.render.apply(this, arguments);
};
}
return target[prop];
},
});
});

params = await page.evaluate(() => {
return new Promise((resolve) => {
setTimeout(() => resolve(window.params || null), 5000);
});
});

if (!params) {
await page.waitForTimeout(3000);
}
}

console.log("Turnstile Params:", params);
} finally {
await browser.close();
}
})();
Вариант 3 (Node.js)
import { chromium } from "playwright";
import { Buffer } from "buffer";

(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();

let websiteKey = null;

while (!websiteKey) {
await page.goto("https://example.com");

await page.evaluate(() => {
window.turnstile = new Proxy(window.turnstile, {
get(target, prop) {
if (prop === "render") {
return function (a, b) {
window.websiteKey = b.sitekey;
return target.render.apply(this, arguments);
};
}
return target[prop];
},
});
});

websiteKey = await page.evaluate(() => {
return new Promise((resolve) => {
setTimeout(() => resolve(window.websiteKey || null), 5000);
});
});

if (!websiteKey) {
await page.waitForTimeout(3000);
}
}

const html = await page.content();
const htmlPageBase64 = Buffer.from(html).toString("base64");

const result = {
websiteKey,
htmlPageBase64,
};

console.log(result);

await browser.close();
})();

Используйте библиотеку SDK

// https://github.com/ZennoLab/capmonstercloud-client-js

import { CapMonsterCloudClientFactory, ClientOptions, TurnstileRequest } from '@zennolab_com/capmonstercloud-client';

document.addEventListener('DOMContentLoaded', async () => {
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({ clientKey: '<your capmonster.cloud API key>' }));
console.log(await cmcClient.getBalance());

const turnstileRequest = new TurnstileRequest({
websiteURL: 'https://tsinvisble.zlsupport.com',
websiteKey: '0x4AAAAAAABUY0VLtOUMAHxE',
cloudflareTaskType: 'cf_clearance',
proxyType: 'http',
proxyAddress: '8.8.8.8',
proxyPort: 8080,
proxyLogin: 'proxyLoginHere',
proxyPassword: 'proxyPasswordHere',
pageData: 'pageDataHere',
data: 'dataHere',
htmlPageBase64: 'htmlPageBase64Here',
userAgent: 'userAgentHere',
});

console.log(await cmcClient.Solve(turnstileRequest));
});