Вы установили антифрод-скрипт. Он собирает canvas fingerprint, проверяет WebGL, анализирует движения мыши. Отчёт показывает, что 95% визитов — настоящие люди. Но конверсия падает, бюджет утекает, а заявки не растут. Проблема в том, что современные боты давно научились проходить любые JavaScript-проверки. Детекция ботов без JavaScript — на уровне сетевых протоколов — единственный подход, который невозможно обмануть клиентским кодом.
В этой статье разберём, почему JS-проверки стали неэффективны, какие серверные методы существуют, и как архитектура обратного прокси позволяет выявлять ботов ещё до того, как страница начнёт загружаться.
Почему JavaScript-детекция ботов перестала работать
Индустрия антифрода десятилетиями строилась на JavaScript. Логика была простой: вставляем скрипт на страницу, он опрашивает браузер, собирает отпечатки, сравнивает с эталоном. Если что-то не совпадает — бот. Эта модель сломалась по трём направлениям.
Headless-браузеры исполняют JS безупречно
Puppeteer, Playwright и Selenium запускают полноценный движок Chromium или Firefox. Они отвечают на все вопросы антифрод-скрипта ровно так, как отвечает настоящий браузер, потому что они и есть настоящий браузер — просто управляемый программой, а не человеком. Canvas fingerprint, WebGL renderer, AudioContext — всё идентично обычному Chrome.
Антидетект-браузеры подменяют всё
Инструменты вроде Multilogin, GoLogin и Dolphin Anty создают виртуальные профили с полностью настраиваемыми отпечатками. Оператор задаёт конкретный User-Agent, разрешение экрана, набор шрифтов, параметры WebGL — и каждый профиль выглядит как уникальный реальный пользователь. JS-проверка видит «человека из Москвы на Windows 11 с Chrome 124», хотя на самом деле это ферма из 500 профилей на одном сервере.
Скрипты блокируются и модифицируются
Боты могут просто не загружать антифрод-скрипт. Перехват на уровне прокси, подмена ответа сервера, блокировка домена скрипта — всё это тривиальные операции. Даже если скрипт загрузится, его можно модифицировать в рантайме, перехватив API-вызовы через Proxy объекты JavaScript, чтобы он всегда возвращал «чистый» результат.
Более того, даже если JS-скрипт сработает корректно, он обнаружит проблему постфактум — когда страница уже загружена, рекламный клик уже засчитан, а бюджет уже потрачен. Время между загрузкой страницы и получением вердикта от JS-антифрода составляет от 500 миллисекунд до нескольких секунд. За это время рекламная платформа уже зафиксировала визит.
Итог: любая защита, которая полагается на код, исполняемый в браузере клиента, находится на территории противника. Бот контролирует среду исполнения и может подделать любой ответ.
Детекция ботов без JavaScript: серверные методы, которые нельзя подделать
Принципиальное отличие серверной детекции в том, что она анализирует данные, которые клиент отправляет ещё до получения контента. Бот не может подделать TCP-пакет так же легко, как значение navigator.userAgent, потому что TCP-стек формируется ядром операционной системы, а не пользовательским кодом.
1. TCP fingerprinting: отпечаток на уровне SYN-пакета
Каждое TCP-соединение начинается с SYN-пакета. В нём операционная система указывает параметры, которые характеризуют её сетевой стек:
- Window Size — начальный размер окна приёма. Windows, Linux и macOS используют разные значения по умолчанию.
- MSS (Maximum Segment Size) — максимальный размер сегмента. Зависит от MTU интерфейса и ОС.
- TTL (Time To Live) — начальное значение. Windows ставит 128, Linux — 64, macOS — 64 с определёнными вариациями.
- TCP Options и их порядок — набор и последовательность опций (MSS, Window Scale, SACK Permitted, Timestamps, NOP) уникальны для каждой ОС и её версии.
Что это даёт: если User-Agent заявляет Chrome на Windows 11, а TCP fingerprint соответствует Linux-серверу — перед нами автоматизация из дата-центра. Бот не может подменить эти параметры без модификации ядра ОС или использования специализированного сетевого стека, что на порядок сложнее, чем подмена JS-свойства.
2. TLS fingerprinting: JA3, JA4 и анализ ClientHello
При установке TLS-соединения клиент отправляет сообщение ClientHello, которое содержит детальную информацию о его криптографических возможностях:
- Наборы шифров (Cipher Suites) — их список и порядок уникальны для каждого TLS-клиента.
- TLS-расширения — какие расширения поддерживает клиент, в каком порядке они указаны.
- Поддерживаемые группы и форматы точек эллиптических кривых — характеристики криптографии.
- Версия TLS — реальная поддерживаемая версия (не только объявленная).
Эти данные агрегируются в хеши JA3 и JA4. Chrome 124 на Windows имеет конкретный JA3-хеш. Python-библиотека requests — совершенно другой. Golang net/http — третий. Даже если бот подменил User-Agent на строку Chrome, его TLS-отпечаток выдаёт реальный клиент.
Важный момент: TLS ClientHello отправляется до того, как сервер вернёт хотя бы один байт контента. Детекция происходит мгновенно, с нулевой задержкой для пользователя.
Существуют библиотеки, которые пытаются имитировать TLS-отпечаток Chrome (например, utls для Go или tls-client для Python). Однако они требуют постоянного обновления вслед за каждым релизом браузера и часто отстают, создавая характерные «полу-Chrome» отпечатки, которые сами по себе становятся маркером автоматизации.
3. HTTP/2 fingerprinting: отпечаток на уровне протокола
HTTP/2 — стандартный протокол для современных браузеров, и его реализация тоже уникальна для каждого клиента:
- SETTINGS frame — при установке HTTP/2-соединения клиент отправляет фрейм с настройками: HEADER_TABLE_SIZE, ENABLE_PUSH, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, MAX_FRAME_SIZE. Значения и их порядок специфичны для каждого браузера.
- Порядок псевдо-заголовков — Chrome отправляет
:method,:authority,:scheme,:path. Firefox использует другой порядок. - Приоритеты потоков — схема приоритизации запросов (weight, dependency) различается между браузерами.
- WINDOW_UPDATE — стратегия управления потоком данных.
HTTP/2-отпечаток — один из самых надёжных маркеров, потому что его крайне сложно подделать. Для этого нужно написать собственную реализацию HTTP/2-стека, полностью имитирующую поведение целевого браузера.
4. IP-репутация и ASN-анализ
Каждый IP-адрес принадлежит автономной системе (ASN), и тип этой системы — мощный сигнал:
- Дата-центровые IP — адреса Amazon AWS, Google Cloud, DigitalOcean, Hetzner и сотен других хостинг-провайдеров. Настоящий пользователь крайне редко заходит на сайт с IP дата-центра.
- Residential IP — адреса домашних интернет-провайдеров. Ожидаемый источник реального трафика.
- Mobile IP — адреса мобильных операторов. Легитимный мобильный трафик.
- Residential proxy — отдельная категория: IP формально жилой, но используется через прокси-сеть. Выявляется по базам известных прокси-сервисов и по поведенческим аномалиям.
ASN-анализ не даёт стопроцентного вердикта сам по себе, но в комбинации с другими сигналами резко повышает точность. Визит с IP Amazon AWS, где JA3-хеш соответствует Python requests, а User-Agent заявляет Chrome — это бот с вероятностью, близкой к абсолютной.
Распространённая тактика ботоводов — покупка резидентных прокси для маскировки дата-центровых IP. Но даже при использовании жилого IP остальные сетевые отпечатки (TCP, TLS, HTTP/2) по-прежнему выдают автоматизацию. Резидентный прокси меняет только последний хоп — он не может изменить то, как клиент формирует TCP-пакеты или TLS-сообщения.
5. Анализ HTTP-заголовков
Порядок и состав HTTP-заголовков — ещё один маркер, который сложно подделать:
- Порядок заголовков — браузеры отправляют заголовки в определённой последовательности. Chrome ставит
sec-ch-uaпередsec-ch-ua-mobile. Скрипт на Python расставит их иначе. - Accept-Language — настоящий браузер отправляет язык ОС с приоритетами (например,
ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7). Бот часто ставитen-USили забывает этот заголовок вовсе. - Отсутствие заголовков — современный Chrome отправляет
sec-ch-ua,sec-fetch-dest,sec-fetch-modeи другие Client Hints. Их отсутствие при заявленном Chrome User-Agent — верный признак подделки. - Консистентность — User-Agent говорит «macOS», а Accept-Language содержит только
zh-CNбез упоминания английского. Формально возможно, но статистически крайне маловероятно для типичного трафика.
6. Версия TLS и поддержка шифров
Отдельно стоит обратить внимание на уровень криптографической поддержки:
- Только TLS 1.2 — все современные браузеры поддерживают TLS 1.3. Клиент, который подключается только по TLS 1.2, — это либо устаревший корпоративный софт, либо скрипт на старой версии библиотеки.
- Отсутствие современных шифров — если ClientHello не содержит
TLS_AES_128_GCM_SHA256иTLS_AES_256_GCM_SHA384, клиент не соответствует профилю современного браузера. - Необычный набор шифров — некоторые HTTP-клиенты (curl, wget, httpx) имеют характерные наборы шифров, которые мгновенно идентифицируют их, независимо от User-Agent.
Почему серверная детекция ботов без JavaScript превосходит клиентскую
Фундаментальное преимущество серверного подхода — асимметрия затрат. Подделать значение JavaScript-свойства — одна строка кода. Подделать TCP-стек — месяцы работы с сетевым ядром. Подделать TLS-отпечаток — написание собственной TLS-библиотеки. Подделать всё одновременно и консистентно — задача, которую решают единицы.
Работает до загрузки страницы. Серверные методы анализируют соединение на этапе TCP handshake и TLS negotiation. Решение принимается за миллисекунды до того, как сервер отправит хотя бы один байт HTML. Для легитимного пользователя задержка равна нулю.
Невозможно заблокировать. JS-скрипт можно не загрузить, модифицировать или подменить. TCP SYN-пакет и TLS ClientHello — обязательные части протокола. Без них соединение просто не установится.
Не зависит от контента. Серверная детекция работает одинаково для HTML-страниц, API-запросов, загрузки изображений — для любого HTTP-взаимодействия. JS-детекция работает только на страницах, куда встроен скрипт.
Единая точка контроля. Серверная детекция покрывает все домены и поддомены, маршрутизируемые через прокси. Не нужно встраивать скрипт в каждую страницу, проверять, что он не упал, не был заблокирован AdBlock-ом и корректно загрузился. Один инфраструктурный слой — и всё защищено.
Сравнительная таблица: JS-детекция против серверной детекции ботов без JavaScript
| Критерий | JS-детекция | Серверная детекция |
|---|---|---|
| Момент срабатывания | После полной загрузки страницы и исполнения скрипта | На этапе TCP/TLS handshake, до отправки контента |
| Headless-браузеры (Puppeteer, Playwright) | Не обнаруживает — движок идентичен реальному браузеру | Обнаруживает по TLS/HTTP/2 отпечатку и IP дата-центра |
| Антидетект-браузеры | Не обнаруживает — все отпечатки подменены | Частично обнаруживает по аномалиям TCP/TLS |
| Скрипты (Python, Go, curl) | Не работает — скрипты не исполняют JS | Обнаруживает мгновенно по TLS/TCP/HTTP fingerprint |
| Блокировка защиты | Скрипт можно заблокировать или подменить | Невозможно — протокольный обмен обязателен |
| Влияние на скорость загрузки | Добавляет 50-200 мс на исполнение скрипта | Нулевое — анализ происходит в рамках handshake |
| API-запросы | Не покрывает — скрипт не встроен в API | Полное покрытие всех HTTP-запросов |
| Поведенческий анализ (мышь, клавиатура) | Да | Нет — требует JS как дополнительный сигнал |
| Сложность обхода для атакующего | Низкая — одна строка JS | Высокая — требует модификации сетевого стека |
Реальный сценарий: идеальный JS-отпечаток, пойманный по TLS
Рассмотрим конкретную ситуацию. На рекламную кампанию в Яндекс.Директ приходит трафик. JS-антифрод-система рапортует: всё чисто. Canvas fingerprint — уникальный. WebGL renderer — NVIDIA GeForce RTX 3060. User-Agent — Chrome 124 на Windows 11. Мышь двигается, клавиатура работает, скролл естественный.
Но серверная система видит другую картину:
- TCP fingerprint показывает Linux-ядро версии 5.x. Для «Windows 11» — явное несоответствие.
- JA3-хеш TLS ClientHello не совпадает ни с одним известным хешем Chrome 124. Вместо него — хеш, характерный для модифицированной TLS-библиотеки на базе BoringSSL.
- HTTP/2 SETTINGS фрейм содержит значения INITIAL_WINDOW_SIZE и MAX_CONCURRENT_STREAMS, не соответствующие ни одному известному браузеру.
- IP-адрес принадлежит ASN Hetzner — крупнейшему европейскому хостинг-провайдеру.
- Порядок HTTP-заголовков не совпадает с паттерном Chrome — отсутствуют заголовки
sec-ch-ua-platformиsec-fetch-user. - Клиент открывает TCP-соединение с прокси. Прокси анализирует SYN-пакет и фиксирует TCP fingerprint.
- Клиент инициирует TLS handshake. Прокси извлекает ClientHello, вычисляет JA3/JA4-хеш, фиксирует TLS fingerprint.
- Клиент отправляет HTTP/2 SETTINGS. Прокси анализирует параметры и порядок псевдо-заголовков.
- Прокси сопоставляет все собранные отпечатки с заявленным User-Agent и IP-репутацией.
- Решение принимается за микросекунды: пропустить запрос к целевому серверу, заблокировать или пометить для дополнительного анализа.
Каждый из этих сигналов по отдельности — повод для подозрения. Вместе они дают однозначный вердикт: это автоматизация. Антидетект-браузер идеально подменил все JS-отпечатки, но не смог изменить поведение сетевого стека операционной системы и TLS-библиотеки.
JS-антифрод этот визит пропустил бы. Рекламный бюджет был бы потрачен впустую.
Этот сценарий — не теоретическая модель. Он воспроизводится ежедневно на тысячах рекламных кампаний. Ботоводы инвестируют в имитацию JS-отпечатков, потому что большинство антифрод-систем смотрят только туда. Серверный слой ломает эту экономику: затраты на обход сетевой детекции на порядки выше, чем на обход JS-проверок.
Архитектура обратного прокси для серверной детекции
Для реализации серверной детекции ботов без JavaScript оптимальна архитектура обратного прокси (reverse proxy). Прокси-сервер размещается между клиентом и веб-сервером. Весь трафик проходит через него, при этом для клиента и для сервера прокси полностью прозрачен.
Как это работает:
Ключевое преимущество: ни клиент, ни веб-сервер не знают о существовании промежуточного слоя. Сайт не нужно модифицировать. Скрипты не нужно встраивать. DNS-запись меняется один раз — и защита начинает работать для всех страниц, API и статических ресурсов одновременно.
Технологии, которые делают это возможным на уровне ядра ОС — eBPF (extended Berkeley Packet Filter). eBPF-программы встраиваются в сетевой стек Linux и анализируют каждый пакет с минимальными накладными расходами, без копирования данных в пользовательское пространство и без влияния на производительность.
Для владельца сайта интеграция выглядит максимально просто: DNS A-запись домена меняется на IP прокси-сервера, и с этого момента каждый входящий запрос проходит через слой серверной детекции. Установка скриптов, модификация кода сайта, интеграция через Tag Manager — ничего из этого не требуется.
Комбинированный подход: сервер как первичный фильтр, JS как дополнительный сигнал
Оптимальная стратегия — не выбирать между серверной и клиентской детекцией, а выстраивать эшелонированную защиту.
Первый эшелон — серверная детекция. Работает мгновенно, отсекает грубую автоматизацию: скрипты, простых ботов, трафик из дата-центров. Этот слой обрабатывает 100% запросов с нулевой задержкой.
Второй эшелон — JavaScript-анализ. Для трафика, прошедшего серверный фильтр, собирает дополнительные сигналы: поведенческий анализ (движение мыши, паттерны скролла, скорость набора), аппаратные отпечатки (canvas, WebGL, AudioContext), проверка на аномалии DOM.
Корреляция сигналов. Серверные и клиентские данные объединяются для финального скоринга. Если серверный слой отметил подозрительный TLS-отпечаток, но JS-слой показывает естественное поведение — это повод для более глубокого анализа, а не для немедленной блокировки. Если оба слоя согласны — решение принимается с высокой уверенностью.
Такая архитектура закрывает оба вектора атаки: серверный слой ловит тех, кто не может подделать сетевой стек, а JS-слой добавляет поведенческий контекст для сложных случаев с антидетект-браузерами.
Заключение
JavaScript-детекция ботов — это необходимый, но недостаточный инструмент. В 2026 году, когда headless-браузеры и антидетект-решения доступны за считанные минуты, полагаться только на клиентские проверки — значит отдавать рекламный бюджет ботоводам.
Детекция ботов без JavaScript — на уровне TCP, TLS, HTTP/2 и IP-репутации — работает там, где клиентский код бессилен. Она анализирует то, что нельзя подделать без фундаментальной переработки сетевого стека. Она срабатывает до загрузки страницы. Она покрывает не только HTML, но и API, статику и любые HTTP-запросы.
Если вы управляете рекламным бюджетом или отвечаете за качество трафика — задайте вашему антифрод-провайдеру простой вопрос: «Что именно вы анализируете на сетевом уровне, до исполнения JavaScript?» Ответ на него покажет, насколько серьёзна защита.