← Все статьи

Что страница на самом деле способна определить о headless-Chrome

4 мин чтения detectionheadlessautomation

Спросите десять человек, определяется ли headless-Chrome, и получите десять ответов, большинство из которых устарели. Честный ответ изменился, когда Chrome пересобрал headless на том же коде, что и полный браузер, и меняется ещё раз в зависимости от того, есть ли у машины видеокарта.

Что выдавал старый headless

Изначальный режим --headless работал по действительно другому пути кода, и это было видно:

Что починил новый headless

Chrome 112 добавил --headless=new, пересобранный на том же коде, что и полный браузер, а не на урезанном конвейере, а Chrome 132 убрал старую реализацию, так что обычный --headless теперь означает новый режим. Старый живёт отдельно как chrome-headless-shell. Строка UA больше не несёт токен HeadlessChrome по умолчанию, navigator.plugins сообщает тот же встроенный набор, что и обычное окно, а outerHeight/outerWidth ведут себя как положено. Большая часть списка выше, та самая, которую до сих пор повторяют по статьям времён до 112-й версии, больше не применима.

Признак, который действительно остался: нет видеокарты

Чего новый headless не починил, потому что это не проблема headless, - это то, что происходит на машине без графического железа.

Рендерер WebGL. Запросите WEBGL_debug_renderer_info и значение UNMASKED_RENDERER_WEBGL. На настоящем десктопе это будет что-то вроде строки ANGLE, называющей реальную видеокарту NVIDIA, AMD или Intel. На headless-сервере без видеокарты Chrome откатывается к программному растеризатору, SwiftShader на большинстве платформ или llvmpipe под Mesa на Linux, и строка так прямо и говорит. Настоящие пользовательские машины практически никогда не работают на программном рендерере WebGL, что делает этот признак одним из самых надёжных серверных.

Отсутствующие кодеки. В минимальных серверных образах часто нет библиотек декодирования H.264 или AAC, которые по умолчанию есть в десктопной ОС, поэтому проверки canPlayType и реальное воспроизведение могут отличаться от того, что сообщает пользовательский браузер.

Доступность шрифтов. На голом Linux-сервере обычно стоит горстка шрифтов, чаще всего DejaVu и Liberation, против трёхсот и более на настоящей установке Windows или Mac. Перечисление шрифтов через метрики текста на canvas - давно известный побочный канал, и он сильно коррелирует с headless-развёртываниями просто потому, что именно там живут минимальные наборы шрифтов.

Ничего из этого не вызвано самим флагом --headless. Всё это вызвано работой на железе и образе ОС, которые никогда не предназначались для отрисовки дисплея, а headless-автоматизация часто именно там и живёт.

Практический вывод

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

Если работать приходится на сервере, решать надо именно историю с видеокартой, а не флаг headless. Виртуальный дисплей и, где возможно, реальный или виртуализованный путь к видеокарте значат больше любой заплатки на UA или плагины, потому что строку рендерера скрипт не может легко подделать, не подделав заодно и саму отрисовку за ней.

Когда бесплатный подход - ответ лучше

Если у вашей задачи вообще нет вопросов с детектом, внутреннее тестирование, скрапинг собственного стенда, генерация PDF, обычные Playwright или Puppeteer в headless по умолчанию бесплатны, хорошо поддерживаются и уже несут описанные выше исправления нового headless. Антидетект-браузер не нужен, чтобы закрывать признаки, которые Chromium закрыл сам.

Где мы честны о своих ограничениях

Опция headless в AntiBrow на macOS сейчас ничего не делает: включение всё равно открывает полноценное окно, потому что эквивалента для macOS пока не реализовано. На Linux headless-отрисовка требует Xvfb, виртуального дисплейного сервера, поскольку браузеру всё равно нужно где-то рисовать, даже если никто не смотрит. Ни то, ни другое не маскируется, потому что читатель выяснит и то и другое за один прогон.

Проверьте сами

Откройте страницу и прочитайте navigator.plugins.length, navigator.userAgent и значение UNMASKED_RENDERER_WEBGL из контекста WEBGL_debug_renderer_info. На новом headless без видеокарты плагины и UA будут выглядеть нормально, а строка рендерера всё равно скажет SwiftShader или llvmpipe. Основную работу сейчас делает именно это поле.

Наш чек-лист согласованности отпечатка разбирает проверки согласованности вокруг этого, включая то, как строка рендерера должна сходиться с заявленной ОС и видеокартой.

Попробуйте на бесплатном тарифе.

Неограниченное число локальных профилей, без карты. Проверьте результат детекторами сами.