Scarnox · Blog

Решатель капчи на Node.js: рабочий пример с fetch (2026)

Решатель капчи на Node.js — это один HTTP-запрос. Node 18 и новее поставляются с fetch, поэтому для вызова API не нужен пакет. Отправьте sitekey и URL страницы, дождитесь ответа и поместите токен в форму. Этот гайд показывает весь поток для PopularCaptcha, которую Scarnox сегодня решает в варианте proxyless.

Начните с пробного баланса, карта не нужна и сначала запустите код ниже на тестовой странице.

Требования

Модуль решателя

Модуль ниже — одна функция. Она отправляет запрос в API с заголовком Bearer, прерывается через 185 секунд и выбрасывает исключение, если errorId не равен 0:

// solver.mjs
const API_URL = "https://api.scarnox.com/api/tasks/create";

export async function solveCaptcha(sitekey, pageUrl, { invisible = false } = {}) {
  const body = {
    captcha_type: "PopularCaptchaTaskProxyless",
    site_key: sitekey,
    site_url: pageUrl,
  };
  if (invisible) body.is_invisible = true;

  const res = await fetch(API_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SCARNOX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(185_000), // вызов возвращается, когда токен готов
  });

  const data = await res.json().catch(() => null);
  if (!data) throw new Error(`HTTP ${res.status}: response was not JSON`);

  if (data.errorId !== 0) {
    throw new Error(`${data.errorCode}: ${data.errorDescription}`);
  }
  return data.solution.token;
}

Опроса нет. Запрос остаётся открытым, пока токен не готов, и при успехе токен лежит в solution.token.

Повторы

Неудачное решение возвращает errorId, отличный от 0, и за него не списывается плата. Короткого цикла повторов достаточно для временных сбоев. Держите число попыток небольшим, чтобы неверный sitekey или URL страницы не тратили время впустую:

export async function solveWithRetry(sitekey, pageUrl, attempts = 3) {
  let lastError;
  for (let i = 1; i <= attempts; i++) {
    try {
      return await solveCaptcha(sitekey, pageUrl);
    } catch (err) {
      lastError = err;
      console.warn(`Attempt ${i} failed: ${err.message}`);
      await new Promise((r) => setTimeout(r, 1000 * i));
    }
  }
  throw lastError;
}

Полную политику ошибок см. в обработке ошибок решателя капчи.

Отправка токена

Токен попадает в поле формы, которое ожидает сайт. Большинство страниц с PopularCaptcha читают h-captcha-response, многие также читают g-recaptcha-response. Чтобы не ошибиться, отправляйте оба:

// submit.mjs
import { solveWithRetry } from "./solver.mjs";

const pageUrl = "https://example.com/signup";
const token = await solveWithRetry("YOUR-SITEKEY-UUID", pageUrl);

const form = new URLSearchParams({
  email: "you@example.com",
  "h-captcha-response": token,
  "g-recaptcha-response": token,
});

const res = await fetch(pageUrl, {
  method: "POST",
  body: form,
  redirect: "manual",
});
console.log("Status:", res.status);

Запуск:

SCARNOX_API_KEY=scarnox_YOURAPIKEY node submit.mjs

Обычный fetch не сохраняет cookie между запросами. Многие страницы регистрации и поиска привязывают капчу к cookie сессии, поэтому токен, отправленный без подходящего cookie, может быть отклонён. Есть два способа с этим справиться:

Первый вариант подходит, когда форма простая и сайт почти не использует JavaScript. Второй — для всего более сложного.

Практичная проверка: после POST смотрите код статуса и итоговый URL. Редирект на страницу успеха обычно означает, что токен принят. Страница, которая снова показывает виджет, обычно означает отказ или то, что cookie из GET не дошло. Первые несколько запусков логируйте тело ответа, чтобы понять, в каком вы случае.

Тайминг

Токен истекает примерно через две минуты. Решайте близко к моменту отправки. Частая ошибка — решить в начале длинной задачи и отправить позже. Решите и сразу отправьте. Подробнее — в истечении токена капчи.

Невидимые капчи

Если у виджета на странице data-size="invisible", передайте { invisible: true }. Тогда функция отправит с запросом is_invisible: true:

const token = await solveCaptcha("YOUR-SITEKEY-UUID", pageUrl, { invisible: true });

Если страница также привязывает к виджету колбэк, форме может понадобиться вызов этой функции с токеном. Найдите её в скрипте страницы. Шаблоны описаны в гайде невидимая капча.

Парсинг с решателем

Иногда капча появляется на странице, которую вы парсите, а не на форме, которую отправляете. Схема та же: найдите виджет в HTML, решите его и отправьте на URL, куда его отправляет виджет. Держите низкую частоту запросов и сначала проверьте условия сайта. Парсите ответственно: соблюдайте robots.txt, не берите лишних персональных данных и не перегружайте сервер.

Тарифы

Scarnox берёт плату за каждое успешное решение. Неудачные решения не списываются. Актуальные расценки — на странице цен. Чтобы начать, возьмите пробный баланс, карта не нужна.

Что дальше