Как обойти капчу с использованием 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-автоматизация в серверной среде
Подготовка
- Создай проект:
mkdir captcha-playwright && cd captcha-playwright
npm init -y
- Установи зависимости:
npm install playwright node-fetch dotenv
- Создай
.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 это надёжный путь.
Нужна скорость? Не жди, параллелизируй задачи. Нужна надёжность? Используй прокси. Главное — не обходи капчу "на удачу". Лучше сделай это правильно с первого раза.