Playwright для веб-скрапинга: обход JS-рендеринга и антибот-защиты
Как использовать Playwright для парсинга SPA-сайтов, какие сигналы выдают headless-браузер и как их скрыть.

Playwright де-факто стал стандартом для браузерной автоматизации после того, как Microsoft выпустила его как более современную альтернативу Puppeteer. Для скрапинга он особенно ценен тем, что запускает настоящий движок рендеринга — сайт не может отличить его от обычного браузера на уровне DOM.
Но именно на уровне поведения браузера антибот-системы и ловят автоматизацию.
Проблема: headless-браузер не значит невидимый
По умолчанию Playwright оставляет заметные следы:
navigator.webdriver === true— простейшая проверка, которую делает почти любой антибот-скрипт.- Отсутствие типичных плагинов браузера (
navigator.plugins.length === 0). - Идеально ровные тайминги между действиями — человек не кликает с точностью до миллисекунды.
- Характерный TLS-отпечаток (JA3), который у автоматизированных клиентов часто отличается от обычных браузеров.
Cloudflare, DataDome и подобные системы комбинируют десятки таких сигналов и присваивают запросу «скор доверия» — при низком скоре показывают капчу или блокируют доступ.
Базовая настройка Playwright для скрапинга
import { chromium } from "playwright";
const browser = await chromium.launch({
headless: true,
args: ["--disable-blink-features=AutomationControlled"],
});
const context = await browser.newContext({
userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
viewport: { width: 1366, height: 768 },
locale: "ru-RU",
});
const page = await context.newPage();
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });Флаг --disable-blink-features=AutomationControlled убирает часть автоматических признаков Chromium, а явный userAgent и viewport делают контекст менее «дефолтным».
Ожидание динамического контента
Главная причина использовать Playwright вместо HTTP-запросов — SPA-сайты рендерят контент асинхронно. Простое page.goto() не гарантирует, что нужные элементы уже на странице.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/catalog")
# ждём конкретный селектор, а не фиксированную паузу
page.wait_for_selector(".product-card", timeout=15000)
items = page.eval_on_selector_all(
".product-card",
"cards => cards.map(c => ({"
" title: c.querySelector('.title')?.textContent?.trim(),"
" price: c.querySelector('.price')?.textContent?.trim()"
"}))",
)
print(items)
browser.close()Важно
Избегайте page.wait_for_timeout(5000) как основной стратегии ожидания — это медленно и ненадёжно. Ждите конкретное состояние: селектор, сетевой ответ или событие networkidle.
Имитация человеческого поведения
Для сайтов с продвинутой защитой одних заголовков недостаточно — важны паттерны взаимодействия:
// случайные паузы между действиями вместо фиксированных
async function humanDelay(min = 200, max = 800) {
await new Promise((r) => setTimeout(r, min + Math.random() * (max - min)));
}
await page.mouse.move(100, 200);
await humanDelay();
await page.mouse.move(340, 410, { steps: 12 }); // движение в несколько шагов, не телепорт
await humanDelay();
await page.click(".add-to-cart");Ротация identity: user-agent, прокси, контексты
Для парсинга в промышленных масштабах один и тот же IP и fingerprint быстро попадают в бан-лист. Практика:
- Один
BrowserContext— одна «личность» (user-agent + прокси + локаль). Не переиспользуйте контекст между разными «личностями». - Ротируйте резидентные или мобильные прокси для доменов с жёсткой защитой — датацентровые IP вычисляются легко.
- Закрывайте контекст и открывайте новый после N запросов, а не держите один браузер вечно открытым.
Заключение
Playwright решает задачу рендеринга JS-контента, но обход антибот-защиты — это отдельная, постоянно меняющаяся дисциплина: сигналы, по которым вас вычисляют, обновляются так же часто, как и защита от них. Для разовых задач ручная настройка (user-agent, задержки, прокси) обычно достаточна. Для регулярного мониторинга множества защищённых источников поддержка этой инфраструктуры быстро становится отдельным проектом внутри проекта.
Частые вопросы
Playwright лучше Puppeteer или Selenium?+
Playwright поддерживает Chromium, Firefox и WebKit из одного API, имеет встроенное ожидание элементов (auto-waiting) и более стабильную работу с сетевыми запросами. Puppeteer ограничен Chromium, Selenium — более старый и многословный API. Для нового проекта в 2026 году Playwright обычно предпочтительнее.
Как обнаружить, что сайт распознал headless-браузер?+
Обычно это проявляется как капча на каждом запросе, редирект на страницу проверки (Cloudflare challenge) или пустой ответ вместо данных при том, что тот же URL открывается в обычном браузере.
Стоит ли использовать stealth-плагины?+
Они помогают против базовых проверок (navigator.webdriver, WebGL fingerprint), но продвинутые антибот-системы анализируют куда больше сигналов — поведение мыши, тайминги, TLS-отпечаток. Для серьёзной защиты одних плагинов недостаточно.
Похожие материалы

Антибот-защита и парсинг: как снижать риски без гонки вооружений
Разбираем антибот-защиту с точки зрения бизнеса: почему сайты блокируют автоматический сбор, как планировать нагрузку, качество, разрешения и альтернативы API.

Как парсить сайты в 2026 году: полное руководство
Разбираем современные подходы к веб-скрапингу — от простых HTTP-запросов до headless-браузеров и AI-агентов — и когда какой выбрать.

OCR и компьютерное зрение: когда текста на странице недостаточно
Что делать, когда нужные данные — это изображение, скан или текст, встроенный в canvas/WebGL, а не обычный HTML.