Туториалы по обходу капчи

Как обойти капчу с использованием Playwright

Как автоматически решать капчу с использованием Playwright

В статье разбираемся как обходить капчи с использованием Playwright и API сервиса распознавания — с примерами кода и практическими советами.

Обход капч с использованием Playwright

Playwright — это мощный инструмент, но в любой момент может уткнуться в капчу. Если ты автоматизируешь что угодно — от тестирования до сбора данных — капча становится не просто проблемой, а тупиком.

Решение? Делегировать. Сервис 2Captcha умеет распознавать капчи, а Playwright — управлять браузером так, будто им пользуется человек. Вместе они позволяют автоматизировать даже защищённые сценарии.

Возможности Playwright

  • Мультибраузерность: Chromium, Firefox и WebKit — поддерживаются из коробки.
  • Кроссплатформенность: Windows, Linux и macOS — как в CI, так и локально. Можно запускать в headless-режиме.
  • Поддержка разных языков: TypeScript, JavaScript, Python, Java, .NET.
  • Эмуляция мобильных браузеров: Android Chrome и iOS Safari.

Когда это пригодится

  • Парсинг данных с динамических сайтов
  • Автоматизация форм, которые требуют ввода данных после авторизации
  • Обход защиты в одностраничных приложениях (SPA)
  • Написание автотестов, включающих капчу
  • Любая headless-автоматизация в серверной среде

Подготовка

  1. Создай проект:
mkdir captcha-playwright && cd captcha-playwright
npm init -y
  1. Установи зависимости:
npm install playwright node-fetch dotenv
  1. Создай .env с API-ключом:
API_KEY=твой_ключ_2captcha

И подключи его в коде:

require('dotenv').config();
const API_KEY = process.env.API_KEY;

Как определить тип капчи

Чаще всего ты встретишь:

  • reCAPTCHA v2 — "Я не робот" или картинки
  • reCAPTCHA invisible — нет визуального интерфейса, активируется при submit
  • hCaptcha — аналог reCAPTCHA

Ищи data-sitekey в DOM:

<div class="g-recaptcha" data-sitekey="...">

или

<div class="h-captcha" data-sitekey="...">

Чтобы не искать вручную, можно поставить расширение обхода для Chrome — оно показывает тип капчи и sitekey и тип капчи. Подробности в статье - Captcha detector.

Отправка задачи в 2Captcha

const submitCaptcha = async () => {
  const params = new URLSearchParams();
  params.append('key', API_KEY);
  params.append('method', 'userrecaptcha');
  params.append('googlekey', 'SITE_KEY');
  params.append('pageurl', 'https://target-site.com');
  params.append('json', 1);

  const res = await fetch('https://2captcha.com/in.php', {
    method: 'POST',
    body: params,
  });

  const data = await res.json();
  if (data.status !== 1) throw new Error('Ошибка отправки капчи');
  return data.request;
};

Получение токена

const waitForToken = async (captchaId) => {
  const url = `https://2captcha.com/res.php?key=${API_KEY}&action=get&id=${captchaId}&json=1`;

  for (let i = 0; i < 20; i++) {
    const res = await fetch(url);
    const data = await res.json();

    if (data.status === 1) return data.request;
    if (data.request !== 'CAPCHA_NOT_READY') throw new Error(data.request);
    await new Promise(r => setTimeout(r, 5000));
  }

  throw new Error('Таймаут ожидания токена');
};

Отправка формы

await page.evaluate((token) => {
  const el = document.querySelector('[name="g-recaptcha-response"]');
  if (el) el.value = token;
  else {
    const textarea = document.createElement('textarea');
    textarea.name = 'g-recaptcha-response';
    textarea.style.display = 'none';
    textarea.value = token;
    document.body.appendChild(textarea);
  }
}, token);

await page.click('#submit-button');

Полный рабочий пример

Работает на демо-странице Google reCAPTCHA.

require('dotenv').config();
const fetch = require('node-fetch');
const { chromium } = require('playwright');

const API_KEY = process.env.API_KEY;
const SITE_URL = 'https://www.google.com/recaptcha/api2/demo';
const SITE_KEY = '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'; // Google's test site

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

  // Submit captcha to 2Captcha
  const inRes = await fetch('https://2captcha.com/in.php', {
    method: 'POST',
    body: new URLSearchParams({
      key: API_KEY,
      method: 'userrecaptcha',
      googlekey: SITE_KEY,
      pageurl: SITE_URL,
      json: '1',
    }),
  });
  const inData = await inRes.json();
  if (inData.status !== 1) throw new Error('Failed to send captcha');
  const captchaId = inData.request;

  // Wait for solution
  let token;
  for (let i = 0; i < 20; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const res = await fetch(`https://2captcha.com/res.php?key=${API_KEY}&action=get&id=${captchaId}&json=1`);
    const data = await res.json();
    if (data.status === 1) {
      token = data.request;
      break;
    } else if (data.request !== 'CAPCHA_NOT_READY') {
      throw new Error(`Captcha error: ${data.request}`);
    }
  }
  if (!token) throw new Error('Captcha timeout');

  // Inject token into the page
  await page.evaluate((token) => {
    document.querySelector('[name="g-recaptcha-response"]').value = token;
  }, token);

  // Submit form
  await page.click('#recaptcha-demo-submit');

  // Wait for confirmation
  await page.waitForSelector('.recaptcha-success');

  console.log('Captcha solved and submitted.');
  await browser.close();
})();

Что может пойти не так

  • ERROR_CAPTCHA_UNSOLVABLE — задача слишком сложная, повтори отправку
  • CAPCHA_NOT_READY — жди дольше, но не бесконечно
  • Токен вставлен, но ничего не происходит? Возможно, нужно вручную вызвать submit или кликнуть кнопку
  • Браузер не взаимодействует с сайтом — попробуй сменить user-agent или IP

Заключение

Если ты работаешь с публичными сайтами, где есть капчи — связка Playwright и 2Captcha закроет 90% задач. Быстро, просто, стабильно. Это не панацея для всех случаев (например, Geetest и Turnstile требуют отдельных подходов), но для reCAPTCHA и hCaptcha это надёжный путь.

Нужна скорость? Не жди, параллелизируй задачи. Нужна надёжность? Используй прокси. Главное — не обходи капчу "на удачу". Лучше сделай это правильно с первого раза.