Отправка готового токена в JSON-запросе Playwright

Автор: solvethree4 мин на чтение

Перехватите известный JSON POST-запрос приложения и замените его поле CAPTCHA значением solution.token. Заполнение textarea не поможет, если приложение формирует запрос из состояния JavaScript.

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

На этой странице

Адаптируйте пример к своему приложению

  1. 1.

    Подготовьте решатель

    Используйте Node.js 22+, Playwright и официальный JavaScript SDK. Следуйте инструкциям по установке SDK; скачивайте пакет указанным в документации способом, не предполагая, что он доступен в реестре npm. Храните SOLVETHREE_API_KEY в процессе Node.js, а не в браузерном коде.

  2. 2.

    Настройте сайт и прокси

    Укажите в TARGET_URL адрес принадлежащей вам тестовой страницы, а в SOLVETHREE_PROXY — URL её HTTP- или HTTPS-прокси. В примере запрашивается действие login для имени хоста страницы. Для этого имени хоста нужен активный профиль рабочего пространства; сначала настройте профиль сайта. Измените действие, если ваше приложение использует другое.

  3. 3.

    Определите точный запрос отправки

    Укажите в TARGET_SUBMIT_URL адрес конечной точки для POST-запроса с JSON, включая путь. У неё должен быть тот же origin, что и у страницы. Пример ожидает объект с полем recaptchaToken и кнопку, доступное имя которой в точности равно Submit. Меняйте эти зависящие от приложения параметры вместе.

Для тестового стенда используйте страницу, которая отправляет JSON-объект на эту конечную точку и возвращает ответ, доступный для проверки. Добавьте ещё одно поле и поле CSRF, чтобы убедиться, что ни одно из них не меняется. Локальный стенд, который лишь возвращает полученные данные, может продемонстрировать изменение JSON, но не проверяет принятие CAPTCHA. Приведённый пример всё равно выполняет реальное решение и требует настроенного сайта, доступного через прокси.

Получите решение, перехватите запрос и отправьте его

Playwright · замена одного известного параметра токена в JSON
import { chromium } from 'playwright';
import { Solvethree } from '@solvethree/sdk';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
const target = new URL(process.env.TARGET_URL);
const proxy = new URL(process.env.SOLVETHREE_PROXY);
const result = await client.solve({ site: target.hostname, action: 'login', proxy: process.env.SOLVETHREE_PROXY });
const proxyConfig = { server: `${proxy.protocol}//${proxy.host}`, username: decodeURIComponent(proxy.username), password: decodeURIComponent(proxy.password) };

const submit = new URL(process.env.TARGET_SUBMIT_URL);
if (submit.origin !== target.origin) throw new Error('Use this demo with a same-origin submission URL');
const browser = await chromium.launch();
try {
  const context = await browser.newContext({ proxy: proxyConfig, userAgent: result.solution.userAgent,
    extraHTTPHeaders: { 'sec-ch-ua': result.solution.secChUa } });
  const page = await context.newPage();
  await page.route(submit.href, async route => {
    if (route.request().method() !== 'POST') return route.continue();
    const body = route.request().postDataJSON();
    if (!body || typeof body !== 'object' || Array.isArray(body)) throw new Error('Expected the known JSON object');
    await route.continue({ postData: JSON.stringify({ ...body, recaptchaToken: result.solution.token }),
      headers: { ...route.request().headers(), 'content-type': 'application/json' } });
  });
  await page.goto(target.href);
  const outcome = page.waitForResponse(r => r.url() === submit.href && r.request().method() === 'POST');
  await page.getByRole('button', { name: 'Submit', exact: true }).click();
  console.log('Application HTTP status:', (await outcome).status());
  // recaptchaToken, the Submit button and this endpoint belong to this demo app.
  // Adapt them to the real application, retaining its session/CSRF data.
  await context.close();
} finally { await browser.close(); }

client.solve создаёт задачу и опрашивает её до готовности либо выбрасывает исключение. Затем пример создаёт браузерный контекст с solution.userAgent, solution.secChUa и тем же единственным прокси, который был передан для решения. SDK не применяет решение к браузеру; это делает обработчик маршрута.

Браузерный контекст создаётся заново. Если для отправки нужна аутентификация или другая подготовка сеанса, выполните её в этом контексте до отправки. Пример не импортирует существующий браузерный сеанс.

Заменяйте токен, а не весь запрос

Маршрут регистрируется до перехода на страницу и ограничен настроенным URL отправки. Запросы с методом, отличным от POST, проходят без изменений. Для POST обработчик читает существующий JSON-объект, копирует его поля и заменяет только recaptchaToken.

Это сохраняет поля тела запроса, например значения формы и данные CSRF. Обработчик также копирует заголовки запроса и устанавливает тип содержимого JSON. Сохраняйте существующую логику сеансов и CSRF приложения: полученный токен не заменяет ни то ни другое.

Не распространяйте маршрут на все запросы и не заменяйте произвольное поле только потому, что оно похоже на токен. Изучите исходящий запрос принадлежащего вам приложения и используйте фактическое имя поля. Этот пример не обнаруживает виджеты, не вызывает произвольные обратные вызовы и не поддерживает произвольные сторонние страницы. Механизм перехвата описан в документации Playwright по сети.

Проверьте ответ приложения

Ожидание ответа начинается до нажатия и сопоставляет URL отправки и метод POST. Записываемый в журнал статус относится к ответу приложения, а не к задаче solvethree. Проверьте тело этого ответа или итоговое состояние приложения по его собственным критериям успеха. Ни готовность задачи, ни успешный HTTP-статус сами по себе не доказывают, что приложение приняло токен.

Ожидание ответа не завершается.

Проверьте, отправляет ли именно кнопка Submit POST-запрос на настроенный URL.

Попробуйте: Исправьте локатор кнопки, конечную точку или метод в соответствии с приложением. Не расширяйте перехват на посторонний трафик.

Маршрут не может прочитать JSON-объект.

Проверьте тело запроса и тип содержимого.

Попробуйте: Используйте этот обработчик только для известной конечной точки, принимающей JSON-объект. Данные форм, массивы и другие форматы полезной нагрузки требуют иной обработки.

Задача готова, но приложение отклоняет отправку.

Проверьте наличие solution.token в исходящем JSON, затем проверьте данные сеанса/CSRF, действие, возвращённые идентификационные данные браузера и прокси.

Попробуйте: Исправьте несоответствия в запросе, прежде чем платить за ещё одно решение. Используйте в браузере прокси, через который выполнялось решение, и возвращённые идентификационные данные.

Решение завершается ошибкой до открытия браузера.

Отличайте ошибку HTTP-запроса от окончательного сбоя задачи. Для неудачной задачи проверьте errorCode и error.

Попробуйте: Исправьте указанную проблему с входными данными, профилем или подключением, а не повторяйте запрос с неизменными данными. См. обработку ошибок API.

Запустите первую задачу.

Начните с $5 на балансе рабочего пространства.

Создать рабочее пространство
Отправка готового токена в JSON-запросе Playwright · solvethree