Headless Browser Detection: як сайти розпізнають Puppeteer, Playwright і Selenium

Headless browser detection поєднує сигнали WebDriver, DevTools Protocol, fingerprint і поведінки, щоб відокремити автоматизовані сесії від звичайного браузингу.
Headless режим корисний для QA, регресійних тестів, доступності та дозволених внутрішніх workflow. Але браузер без вікна часто має інший стартовий стан, часові характеристики й набір можливостей. Виявлення автоматизованого браузингу рідко тримається на одному прапорці: сучасний WAF оцінює сукупність доказів і репутацію сесії.
Puppeteer, Playwright і Selenium не є «ботами» самі по собі. Це інструменти керування браузером. Проблема виникає, коли система намагається видати тестове середовище за звичайного відвідувача або порушує правила ресурсу. Для легітимної автоматизації кращий шлях це узгоджений профіль, прозора авторизація та офіційний API.
Що таке headless browser і де він доречний
Headless browser запускає браузерний рушій без видимого вікна. Він будує DOM, виконує JavaScript, завантажує CSS і мережеві ресурси, тому підходить для end-to-end тестів і рендерингу. Headless browsing не означає відсутність графіки: сучасний Chrome може працювати через реальний rendering pipeline, хоча спосіб запуску все одно залишає контекстні ознаки.
Puppeteer тісно працює з Chromium через Chrome DevTools Protocol. Playwright уміє керувати кількома рушіями й створювати ізольовані browser contexts. Selenium реалізує стандарт WebDriver та керує браузером через драйвер. Відрізняються API та архітектура, але захисний сервіс бачить результат: властивості клієнта, послідовність подій, мережевий слід і дії в сесії.
Для власної QA-системи обирайте headless за швидкістю і відтворюваністю, а headed режим за потреби налагодження. Не робіть висновок, що headed автоматично виглядає як людина. Це лише інший режим виконання.
Які маркери Puppeteer, Playwright і Selenium перевіряють сайти
Найвідоміший маркер це navigator.webdriver. Стандартна властивість може повідомляти сторінці, що браузером керує WebDriver. Вона корисна для власних тестів, але не є достатньою для антифроду: її відсутність нічого не доводить, а присутність трапляється і в корпоративних QA-середовищах.

Інші маркери виникають у момент запуску: аргументи процесу, automation extension, змінні середовища драйвера, порожні властивості window, специфічні глобальні об'єкти або нетипові permission states. Headless середовище може мати 0×0 вікно, неприродний outerWidth, порожній список плагінів, відсутній PDF viewer чи скорочений перелік медіакодеків. Це не універсальні правила. Версії браузерів швидко змінюються.
// Діагностика на власній тестовій сторінці, не механізм обходу
const report = {
webdriver: navigator.webdriver,
viewport: [window.innerWidth, window.innerHeight],
outerWindow: [window.outerWidth, window.outerHeight],
plugins: navigator.plugins.length,
language: navigator.language
};
console.table(report);
Важливішою є узгодженість. Наприклад, User-Agent може заявляти сучасний desktop Chrome, а navigator.plugins, screen, timezone, WebGL, Client Hints і media capabilities можуть описувати мінімальний контейнер. Один зсув не страшний. П'ять незалежних зсувів створюють сильний класифікаційний сигнал.
Як CDP і timing leaks проявляють інструментування
Chrome DevTools Protocol дає автоматизації потужний доступ: виконання скриптів, мережеві перехоплення, DOM-інспекція, емуляція пристрою. Водночас інструментування іноді змінює порядок подій, стек викликів, формати помилок або час серіалізації об'єктів у console-подібних API. Деякі детектори навмисно створюють getter чи Error і дивляться, чи була незвична взаємодія з об'єктом.
Timing leak це не магічний тест. Виконання залежить від CPU, навантаження, GC, мережі та scheduler контейнера. Якісний WAF збирає багато вимірювань і оцінює розподіл, а не ставить блок через одну затримку. Для розробника це означає: не підганяйте затримки випадковими sleep. Такий код робить тест крихким і не відтворює реальну взаємодію.

Схема показує, що WAF формує рішення після кореляції кількох незалежних шарів, а не через одну JavaScript-властивість.
Чому WAF оцінюють fingerprint, мережу і поведінку разом
Cloudflare Turnstile, DataDome, Akamai та подібні рішення працюють як системи оцінки ризику, а не як перевірка однієї JavaScript-властивості. Вони можуть зіставляти стабільність fingerprint, TLS та HTTP-ознаки, репутацію IP, історію cookie, швидкість переходів, pointer events, фокус вікна і реакцію на challenge. Точний набір правил закритий і змінюється, тому твердження про «одну обов'язкову ознаку» застаріває швидко.
Поведінковий шар особливо важливий. Фізичне введення породжує нерівні потоки pointer, wheel і keyboard подій. Автоматизація може мати ідеально рівні інтервали, миттєве заповнення полів, однакові паузи або відсутність звичних blur/focus переходів. І навпаки, ідеально намальована траєкторія миші не робить сесію легітимною. Антифрод бачить ширший контекст.
| Шар перевірки | Приклади сигналів | Чому одиночного сигналу недостатньо |
|---|---|---|
| браузер | WebDriver, plugins, codecs, screen | версії та політики ОС відрізняються |
| CDP і runtime | глобальні об'єкти, помилки, event order | інструменти та браузери еволюціонують |
| мережа | IP, TLS, HTTP-заголовки, гео | законні користувачі працюють через VPN і офіси |
| поведінка | темп, фокус, pointer, навігація | доступність і QA можуть виглядати нетипово |
Як побудувати контрольований стенд для headless detection
Контрольований стенд потрібен, щоб відрізнити реальний артефакт автоматизації від випадкової різниці середовища. Один запуск на ноутбуці розробника нічого не доводить. Мінімальна матриця має охоплювати headed і headless режими, чистий та повторно використаний профіль, актуальну й попередню версію Chromium, а також щонайменше два мережеві маршрути з відомою репутацією. Кожну комбінацію запускають кілька разів із тим самим сценарієм.
Стенд варто розділити на три частини. Контрольна сторінка збирає дозволені browser/runtime-сигнали. Оркестратор запускає браузер і записує конфігурацію. Сховище результатів пов'язує вимірювання з версією рушія, часом запуску та ідентифікатором тесту. Сирі cookies, токени й паролі до набору не входять.
Яку матрицю запусків використовувати
Змінюйте лише один фактор за раз. Спочатку порівняйте headed і headless для одного binary, профілю та IP. Потім замініть версію браузера, не торкаючись мережі. Окремо протестуйте clean profile проти warmed profile, де вже є історія cookies і cache. Такий дизайн показує, що саме створило різницю.
| Фактор | Контрольне значення | Варіант | Що вимірювати |
|---|---|---|---|
| режим | headed | headless | runtime та rendering-відмінності |
| профіль | clean | reused | storage, permissions, history |
| браузер | current | previous | регресії після оновлення |
| мережа | allowlisted IP | corporate route | IP, TLS та latency |
| введення | manual baseline | test script | event order і timing |
Для статистики корисні не лише середні значення. Записуйте медіану, міжквартильний розмах і частку невдалих запусків. Timing-сигнали мають важкі хвости через garbage collection і scheduler, тому один повільний виклик не можна трактувати як доказ.
Яку CDP і Runtime telemetry збирати
Для власної контрольної сторінки достатньо журналювати порядок lifecycle-подій, створення execution contexts, помилки JavaScript, доступність ключових API та часові інтервали між навігацією, DOMContentLoaded і завершенням тестової дії. Не потрібно збирати приватний вміст сторінки. Мета полягає у відтворюваності, а не в спостереженні за користувачем.
CDP telemetry треба відділяти від сигналів, доступних звичайному JavaScript. Якщо детектор знає інформацію лише тому, що test harness сам відкрив DevTools-сеанс, це лабораторний артефакт. Він не обов'язково існує для production-відвідувача. У звіті позначайте джерело кожного поля: page API, browser log, network capture або оркестратор.
Практичний запис одного запуску може містити test_id, Chromium build, launch mode, profile age, viewport, locale, proxy route, timestamps і перелік помилок. Секрети редагують до збереження. Для порівняння зручно обчислювати diff між двома запусками, але оригінальні значення все одно потрібні для пояснення причини.
Три CDP-домени дають найбільше корисного сигналу для власного стенду. Page фіксує момент frameStartedLoading і navigatedWithinDocument, Runtime показує executionContextCreated і послідовність виконання скриптів, а Network відкриває responseReceived та loadingFinished із точними мітками часу. Коли ці події йдуть у нетиповому порядку відносно DOMContentLoaded, це радше ознака зовнішнього інструментування, ніж повільного рендерингу на слабкому CI-раннері. Для контрольної сторінки досить логувати три домени як JSON-рядок на подію і зіставляти отриманий таймлайн із фінальним результатом тесту: allow, challenge чи блок. Такий лог не потребує доступу до приватного вмісту сторінки і водночас показує, чи розбіжність виникла через CDP-інструментування, чи через звичайну мережеву затримку. Зберігайте лише агреговані метрики понад кілька прогонів, а не сирий лог кожної сесії, щоб стенд залишався легким для аудиту.
Як перевіряти події та часові витоки
Синтетична взаємодія відрізняється не лише траєкторією миші. Дивіться на послідовність pointerdown, mousedown, focus, input, change і click, а також на властивість isTrusted. Водночас не перетворюйте ці поля на жорстке правило: допоміжні технології, віддалений робочий стіл і корпоративна RPA можуть генерувати нетипову послідовність законно.
Для timing-аналізу повторюйте один тест десятки разів і порівнюйте розподіли. Випадкові паузи не створюють людської поведінки, вони лише додають шум. Корисніше вимірювати причинні зв'язки: чи очікує сценарій появи елемента, чи виконує наступну дію до завершення layout, чи однаково реагує на повільну мережу.
Як інтерпретувати false positives і зміни WAF
False positive виникає, коли дозволена сесія отримує challenge або блок через схожість із автоматизацією. Його не виправляють глобальним вимкненням правила. Потрібно знайти шар, який дав основний внесок, перевірити його на контрольній групі та змінити вагу або умову лише там, де є докази.
Які метрики показують якість детектора
Precision відповідає на питання, яка частка позначених сесій справді належить до небажаної автоматизації. Recall показує, яку частку таких сесій система знаходить. Для бізнесу не менш важливий false positive rate серед звичайних користувачів і challenge completion rate для легітимних відвідувачів. Одна загальна accuracy може приховати проблему через нерівні класи.
Вимірюйте показники окремо для desktop і mobile, різних версій браузерів, accessibility-сценаріїв, корпоративних мереж і тестових роботів. Після релізу Chromium або зміни WAF-політики порівнюйте їх із попереднім baseline. Різкий стрибок challenge на одному сегменті часто означає несумісність, а не раптову хвилю атак.
Як оформити рішення для аудиту
Журнал рішення має містити час, версію правил, псевдонімізований session ID, внесок кожного шару та фінальну дію: allow, challenge або review. Не зберігайте повні поведінкові траси довше, ніж потрібно для розслідування. Доступ до них обмежують ролями, а зміни порогів проходять code review або формальне погодження.
Пояснюваність потрібна і команді підтримки. Формулювання «заблоковано моделлю» нічого не дає. Корисніша відповідь вказує, що спрацювала мережна репутація або конфлікт browser capabilities, і пропонує безпечний шлях перевірки. Такий процес зменшує тиск на команду розробки й не розкриває точні пороги захисту.
Як будувати легітимну автоматизацію без крихких стелс-патчів
Власникам сайтів потрібен allowlist для тестових акаунтів, окремий staging-домен, тестові ключі й спостережуваний User-Agent. Командам, які інтегруються з чужим сервісом, потрібні письмовий дозвіл, rate limits, офіційний API та контакт для помилкових спрацьовувань. «Маскування» WebDriver через патчі сторінки не усуває конфлікти між API і може порушувати умови платформи.
Натомість тестуйте сумісність профілю. У Afina кожен акаунт є ізольованим Chromium-профілем із власними fingerprint, proxy, cookies і cache, а візуальні сценарії можна запускати для дозволених бізнес-процесів. Автоматизація через локальний API дає змогу контролювати запуски та журналювати їх без прихованого втручання в чужі challenge-потоки.
- визначте власника системи, дозвіл і допустиму частоту запитів
- створіть окремий профіль та тестовий акаунт для конкретного workflow
- перевірте UA, timezone, екран, мову й media capabilities на внутрішній контрольній сторінці
- журналюйте помилки WAF та узгоджуйте їх із власником ресурсу замість обходу challenge
- підтримуйте Chromium і бібліотеки автоматизації в актуальному стані
Технічна дисципліна тут корисніша за «стелс»-плагіни. Вони зазвичай виправляють один відомий симптом, залишаючи інші канали суперечливими.
Headless, headed та антидетект-профіль: у чому різниця
Headless це режим запуску. Headed це той самий браузер із вікном. Антидетект-профіль це окреме середовище з ізольованими даними та контрольованою узгодженістю параметрів. Ці поняття перетинаються, але не замінюють одне одного.
| Варіант | Сильна сторона | Типове обмеження |
|---|---|---|
| headless | швидкі CI та регресійні тести | помітні відмінності середовища |
| headed | зручне налагодження і візуальна перевірка | сам по собі не вирішує fingerprint-конфлікти |
| ізольований профіль | розділяє cookies, cache, проксі та параметри | вимагає політики використання й контролю доступу |
Як розслідувати помилкове спрацьовування WAF
Коли легітимний тест отримує challenge або відмову, починайте з доказів, а не зі спроб змінити десятки прапорців браузера. Збережіть request ID, час у UTC, версію браузера, режим запуску, мережевий маршрут, код відповіді та мінімальний HAR або мережевий лог без секретів. Потім відтворіть дію в staging або з тестовим акаунтом. Це відрізняє блок за IP-репутацією від проблеми fingerprint чи бізнес-правила.
Корисно зробити матрицю запусків: один браузер у headed і headless режимах, один дозволений IP та один звичайний корпоративний маршрут, актуальна й попередня версія бібліотеки. Змінюйте за раз один фактор. Інакше команда отримає багато шуму й жодної причини. Порівнюйте не тільки факт блокування, а й момент: до завантаження сторінки, після виконання JavaScript, під час логіну чи після конкретної дії.
Власник WAF може додати окремий тестовий сегмент, service account або правило для підписаного webhook. Це значно безпечніше, ніж перетворювати QA-сценарій на гонитву за непублічними евристиками. І не забувайте про accessibility: screen reader, RPA у бекофісі та корпоративна VDI-інфраструктура можуть бути нетиповими, не будучи зловмисними.
Що має містити безпечний automation runbook
Runbook починається з мети й меж: який ресурс належить компанії, які дані дозволено читати, хто затверджує запуск і як зупинити сценарій. Додайте rate limit, ідемпотентність, випадок повторного запуску, журнал подій і спосіб відкликати токен. Автоматизація, що не вміє зупинятися, перетворює дрібну помилку на інцидент.
Для браузерного кроку окремо фіксуйте профіль, локальне сховище, проксі, версію Chromium та спосіб автентифікації. Не кладіть паролі в код або в HAR-файли. Якщо workflow потрібен багатьом операторам, використовуйте ролі й ізольовані тестові облікові записи. Такий підхід одночасно полегшує аудит і знижує ймовірність того, що WAF побачить хаотичний потік запитів.
Чому оцінка ризику має бути пояснюваною
Антибот-система без журналу причин складно підтримується. Власник ресурсу має бачити, чи рішення вплинуло на доступність WebDriver, конфлікт параметрів, репутацію мережі або аномальний темп дій. Це дає можливість виправити тестовий маршрут без послаблення захисту для всіх. Модель, що повертає лише «бот», підштовхує команди до небезпечного експериментування замість нормальної інтеграції. Пояснюваний результат також полегшує перевірку змін після оновлення Chrome або WAF-політики. Команда може прив'язати поріг ризику до правила та безпечно відкотити реліз, якщо зростає частка помилкових блокувань. Перевіряйте метрики окремо для користувачів, тестових роботів і доступних технологій, щоб не приховати проблему середнім значенням. Матеріал надано виключно в ознайомчих та освітніх цілях.
Для QA це означає чітко відокремити production-відвідувачів від тестів. Для приватності це означає не змішувати сесії та зберігати профільні дані локально. Призначте відповідального за дозвіл запусків, збереження журналів і своєчасне вимкнення сценарію після інциденту. Окремо фіксуйте версію драйвера, часовий пояс, розмір вікна та маршрут мережевого запиту. Afina підтримує ізоляцію таких профілів і сценаріїв, але не гарантує проходження захисних механізмів будь-якого сайту.
СкачатиFAQ — Часті запитання
Що таке headless browser?
Headless browser запускає браузерний рушій без видимого вікна. Його використовують для тестів, рендерингу та дозволеної автоматизації.
Чи завжди navigator.webdriver означає бота?
Ні, це індикатор WebDriver-автоматизації, а не доказ зловмисності. QA та accessibility-тести теж можуть його мати.
Чому Playwright або Puppeteer виявляють сайти?
Сайти аналізують не лише бібліотеку, а сукупність runtime, fingerprint, мережевих і поведінкових ознак. Один маркер рідко вирішальний.
Що таке CDP leak?
CDP leak це побічна ознака керування браузером через Chrome DevTools Protocol. Вона може проявлятися у порядку подій, стеках або обробці об'єктів.
Чи допомагає headed режим пройти WAF?
Headed режим прибирає лише частину різниць headless запуску. Він не гарантує відповідність fingerprint, мережі чи поведінки політиці сайту.
Як законно тестувати WAF із браузерною автоматизацією?
Використовуйте staging, тестові акаунти, allowlist і письмовий дозвіл власника. Логуйте спрацювання та налаштовуйте правила разом із командою захисту.
Чи можна повністю прибрати сліди automation з headless-браузера?
Ні, повністю прибрати всі сліди неможливо, бо WAF оцінює сукупність runtime, мережевих і поведінкових сигналів одночасно. Патч одного параметра усуває лише один із багатьох незалежних маркерів.
Що робити, якщо WAF блокує легітимний QA-тест?
Зберіть request ID, час, версію браузера і мережевий маршрут, тоді відтворіть дію в staging із тестовим акаунтом. Зверніться до власника ресурсу для white-list замість спроб обійти challenge.
Чим CDP leak відрізняється від timing leak?
CDP leak виникає через сам факт підключення DevTools Protocol і змінює порядок подій чи стек помилок. Timing leak це статистична різниця у швидкості виконання, яку оцінюють за розподілом багатьох вимірювань.
