JA3-fingerprinting: как сеть распознаёт ботов ещё до HTTP-запроса

Автор: BotHunt Editorial
Время чтения: 11 мин.
Просмотров: 5
Дата публикации: 15 июля 2026 г.

Большинство систем защиты смотрят на HTTP: User-Agent, заголовки, cookie, поведение на странице. Проблема в том, что к этому моменту бот уже подключился к серверу — и уже успел себя выдать. Ещё до первого HTTP-запроса, на этапе TLS-рукопожатия, клиент отправляет пакет ClientHello, по которому видно, кто стучится: настоящий Chrome, curl, Python-скрипт или headless-браузер. Именно на этом строится JA3-fingerprinting — снятие TLS-отпечатка клиента.

Мы в BotHunt проверяем TLS-отпечаток каждого соединения на пограничном узле — за миллисекунды и до того, как ваш сервер увидит первый HTTP-заголовок. По нашим данным, значительную долю автоматизированного трафика можно отсеять уже на этом уровне, не тратя ресурсы на разбор запроса. В этой статье разберём, что такое JA3-отпечаток, из чего он собирается, почему в 2023 году он начал «слепнуть» из-за Chrome, чем его заменил JA4 и как TLS-fingerprinting работает в связке с другими сигналами. Без маркетинга — на уровне пакетов и полей ClientHello.

Коротко:

  • JA3-fingerprinting — это отпечаток TLS-клиента, который вычисляется из полей пакета ClientHello (версия TLS, шифры, расширения, кривые) и сворачивается в 32-символьный MD5-хеш.

  • TLS-рукопожатие проходит до HTTP, поэтому подмена User-Agent и заголовков не помогает: JA3 выдаёт бота раньше, чем сервер получит первый запрос.

  • У библиотек Python requests, curl и Go TLS-стек отличается от браузерного, поэтому их JA3 не совпадает ни с одним реальным браузером и легко детектится.

  • С января 2023 года Chrome рандомизирует порядок TLS-расширений, из-за чего классический JA3 стал нестабильным для браузеров — индустрия перешла на JA4 (FoxIO, 2023).

  • TLS-отпечаток не работает в одиночку: из-за CG-NAT и общих браузеров его комбинируют с ASN-репутацией, поведением и browser fingerprint в единый risk-score.

Что такое JA3-fingerprinting простыми словами

JA3-fingerprinting — это способ опознать программу-клиента по тому, как она устанавливает защищённое TLS-соединение. Каждый TLS-клиент (браузер, HTTP-библиотека, бот) при подключении отправляет пакет ClientHello со своим набором параметров. JA3 берёт эти параметры, выстраивает их в строку и хеширует алгоритмом MD5 — получается короткий идентификатор.

Метод придумал Salesforce в 2017 году — изначально для трекинга вредоносного ПО по TLS-рукопожатию. Идея простая: набор шифров и расширений у каждого TLS-стека свой. OpenSSL в Python, BoringSSL в Chrome, NSS в Firefox поддерживают разные алгоритмы и объявляют их в разном порядке. Поэтому отпечаток curl отличается от отпечатка Chrome, даже если бот подставит браузерный User-Agent.

Главное в JA3: он смотрит не на то, что клиент говорит о себе (заголовки легко подделать), а на то, как он технически устанавливает соединение. Подделать это на порядок сложнее, чем сменить строку User-Agent.

Как формируется JA3-хеш: 5 полей ClientHello

JA3-хеш собирается из пяти полей пакета ClientHello, объединённых в одну строку и захешированных MD5. Порядок полей фиксирован, значения записываются в десятичном виде: поля разделяются запятыми, значения внутри поля — дефисами.

Как формируется JA3-хеш из пяти полей ClientHello

Поле

Что содержит

Пример значения

Версия TLS

Максимальная поддерживаемая версия протокола

771 (TLS 1.2)

Cipher suites

Список поддерживаемых наборов шифров

4865-4866-4867-49195…

Extensions

Список расширений TLS в порядке отправки

0-23-65281-10-11…

Elliptic curves

Поддерживаемые эллиптические кривые

29-23-24

EC point formats

Форматы точек эллиптических кривых

0

GREASE-значения (случайные пары вроде 0x0a0a, которые браузеры добавляют для защиты протокола от «окостенения») из строки отбрасываются. Готовая JA3-строка Chrome выглядит примерно так:

771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0

После прогона через MD5 она превращается в 32-символьный отпечаток:

cd08e31494f9531f560d64c695473da9

Именно этот хеш антибот-сервис сравнивает с базой известных отпечатков. Если JA3 совпадает с сигнатурой Python-библиотеки, Go-клиента или headless-фреймворка — соединение сразу помечается как подозрительное, ещё до разбора запроса.

Почему TLS выдаёт бота ещё до HTTP-запроса

TLS-рукопожатие проходит раньше любого HTTP-запроса, а пакет ClientHello отправляется в открытом виде — поэтому сервер видит отпечаток клиента до шифрования и до первого заголовка. Это ключевое свойство JA3: он снимается там, где подмена HTTP-заголовков ещё физически невозможна.

TLS-рукопожатие происходит до HTTP-запроса — этап снятия JA3

Порядок установки соединения выглядит так:

  1. Клиент открывает TCP-соединение с сервером.

  2. TLS handshake: клиент шлёт ClientHello в plaintext — здесь и снимается JA3.

  3. Стороны согласуют ключи и поднимают шифрованный канал.

  4. Только теперь уходит HTTP-запрос с User-Agent, cookie и заголовками.

Отсюда три следствия. Первое: подмена User-Agent не помогает — заголовки идут после рукопожатия, а JA3 снят на шаге 2. Второе: спуфинг HTTP-заголовков вообще не касается TLS-слоя. Третье: бот выдаёт себя раньше, чем сервер потратит ресурсы на разбор запроса, — а значит, отсечь его можно без нагрузки на бэкенд.

Почему у ботов «неправильный» JA3:

  • Python requests / urllib3 используют системный OpenSSL — их отпечаток не совпадает ни с одним браузером.

  • Go-боты (net/http) имеют характерный TLS-стек, давно известный всем антибот-движкам.

  • curl, wget, стоковый Selenium/headless дают узнаваемые сигнатуры из публичных баз JA3.

  • Автоматизация вроде ZennoPoster и BAS часто работает поверх стандартных HTTP-движков, чей TLS-стек не совпадает с реальным браузером.

Показательный пример. Бот на Python requests ставит заголовок User-Agent от Chrome 121 и внешне выглядит как браузер. Но его JA3 — это отпечаток OpenSSL, которого нет ни у одного Chrome. Антибот видит рассинхрон «браузерный User-Agent + небраузерный TLS» и отклоняет соединение ещё до того, как бот успеет запросить страницу. Никакая ротация заголовков это не чинит — нужен принципиально другой TLS-стек.

Хотите отсекать ботов ещё на TLS-рукопожатии, до нагрузки на сервер? Подключить BotHunt бесплатно →

Почему классический JA3 устарел: Chrome 110 и рандомизация

С января 2023 года (Chrome 110) браузер случайным образом перемешивает порядок TLS-расширений при каждом соединении — из-за этого JA3-хеш перестал быть стабильным для браузеров. Раньше порядок расширений был фиксированным, и один браузер давал один JA3. Теперь порядок меняется от соединения к соединению.

Масштаб: рандомизация даёт свыше 20 триллионов возможных JA3-хешей для одного и того же Chrome. Цель Google — не дать экосистеме «закостенеть» вокруг фиксированного порядка (защита от ossification). Побочный эффект — по JA3 стало нельзя надёжно сказать «это именно Chrome 121».

Парадокс в том, что для детекта ботов это скорее плюс. Настоящий Chrome теперь генерирует случайный, но валидный набор расширений. А боты на статичных библиотеках по-прежнему отдают один и тот же фиксированный JA3 — и на фоне рандомизированного браузерного трафика выделяются ещё заметнее. Проблема JA3 не в том, что он перестал ловить ботов, а в том, что он перестал точно идентифицировать конкретную версию браузера. Ровно поэтому индустрия перешла на JA4.

JA4 — новый стандарт TLS-отпечатка

JA4 — обновлённый метод TLS-fingerprinting от компании FoxIO (2023), устойчивый к рандомизации. Он сортирует расширения и шифры перед хешированием, поэтому даёт стабильный отпечаток даже для современного Chrome, который перемешивает порядок.

Сравнение JA3 и JA4: отличия TLS-отпечатков

Что изменилось в JA4:

  • Человекочитаемый трёхчастный формат a_b_c. Часть a — метаданные (версия TLS, число расширений, ALPN, наличие SNI), b — хеш отсортированных шифров, c — хеш отсортированных расширений.

  • Сортировка по hex-значению убивает эффект рандомизации Chrome: порядок больше не влияет на результат.

  • Усечённый SHA-256 вместо MD5.

  • Поддержка QUIC и HTTP/3 — то, чего в JA3 не было.

Пример JA4-строки: t13d1516h2_8daaf6152771_02713d6af862. Префикс читается напрямую: t — TLS поверх TCP, 13 — версия TLS 1.3, d — есть домен в SNI, 15 — 21 шифр, 16 — 22 расширения, h2 — ALPN указывает на HTTP/2. Профиль клиента виден уже по началу строки, без обращения к базе хешей — в этом ещё одно практическое преимущество JA4 над непрозрачным MD5 в JA3.

Параметр

JA3

JA4

Год, автор

2017, Salesforce

2023, FoxIO

Порядок расширений

Как отправлено

Сортировка по hex

Устойчив к рандомизации Chrome

Нет

Да

Алгоритм хеша

MD5

Усечённый SHA-256

QUIC / HTTP3

Нет

Да

Формат

32-символьный хеш

Читаемый a_b_c

К 2026 году JA4 — основной TLS-сигнал у Cloudflare, Akamai и AWS WAF. Спецификация JA4 и эталонные реализации опубликованы в репозитории FoxIO на GitHub, а у Cloudflare есть документация по применению JA3/JA4 в правилах защиты. JA4 особенно эффективен против AI-скрейперов: у многих из них TLS-стек не совпадает с заявленным браузером — подробнее об этом в статье о блокировке AI-ботов GPTBot и ClaudeBot.

BotHunt снимает JA3/JA4 и HTTP/2-отпечаток на edge-узле за миллисекунды. Попробовать 14 дней бесплатно →

HTTP/2-отпечаток: второй сетевой слой до контента

Помимо TLS, бота выдаёт способ, которым клиент открывает HTTP/2-соединение — так называемый Akamai h2 fingerprint, снимаемый до передачи контента. Это второй сетевой отпечаток, дополняющий JA3/JA4.

Когда клиент поднимает HTTP/2, он отправляет SETTINGS-фрейм, WINDOW_UPDATE, задаёт приоритеты потоков и порядок псевдо-заголовков (:method, :authority, :scheme, :path). У браузеров это устроено характерно; у ботов на Go, Python или Node — иначе. Комбинация «JA3/JA4 + HTTP/2-отпечаток» ловит клиентов, которые подделали одно, но забыли про другое: например, TLS выглядит как Chrome, а порядок псевдо-заголовков — как у Python-клиента.

Оба отпечатка снимаются на сетевом уровне, до того как сервер отдаёт HTML. Это и есть суть подхода «палим до HTTP-контента»: к моменту, когда бот мог бы что-то подделать в запросе, решение о нём уже почти принято.

Ограничения TLS-fingerprinting: почему это не серебряная пуля

TLS-отпечаток нельзя использовать в одиночку — он даёт ложные срабатывания и обходится современными инструментами, поэтому работает только как один из сигналов. Честно о его слабых местах:

  • Общий отпечаток. Миллионы людей с одинаковым Chrome дают одинаковый JA4. По нему нельзя выделить конкретного пользователя — только класс клиента.

  • CG-NAT. За одним IP через Carrier-Grade NAT сидят тысячи мобильных пользователей — блокировать по связке IP+JA3 опасно, поймаете живых людей.

  • Обход. Инструменты curl-impersonate (пересобирает TLS на BoringSSL), utls в Go и curl_cffi с профилем impersonate="chrome" копируют браузерный ClientHello почти точно — JA3/JA4 такого бота совпадёт с настоящим Chrome.

  • Легитимные не-браузерные клиенты. Мобильные приложения, API-интеграции, платёжные вебхуки и поисковые боты имеют свои TLS-стеки — рубить их огулом нельзя.

Вывод: TLS-fingerprinting мгновенно и без нагрузки отсеивает дешёвых ботов (Python, curl, стоковый Selenium), но продвинутых с подделанным ClientHello — нет. Против них нужны browser fingerprinting, поведенческая аналитика и машинное обучение, а также ASN-репутация IP. Отпечаток TLS — это быстрый первый фильтр, а не финальный вердикт.

Как BotHunt использует TLS-отпечаток в risk-score

BotHunt снимает JA3/JA4 и HTTP/2-отпечаток на пограничном узле, сверяет их с базой сигнатур и подаёт результат как один из входов в общий risk-score соединения — вместе с ASN, поведением и browser fingerprint. TLS-сигнал не выносит вердикт сам по себе.

Как это устроено по шагам:

  1. На edge-узле, до вашего сервера, мы читаем ClientHello и считаем JA3/JA4. Это занимает доли миллисекунды.

  2. Отпечаток сверяется с базой известных ботов и с ожидаемым для заявленного User-Agent. Рассинхрон вида «UA=Chrome, а JA4=Python» — сильный сигнал бота.

  3. TLS-результат суммируется с ASN-репутацией (дата-центр против домашнего IP), поведением на странице и отпечатком браузера в единый risk-score.

  4. Итоговое решение — пропустить, показать челлендж или заблокировать — принимается менее чем за 15 мс. При сбое действует режим fail-open: ваш сайт не ляжет из-за защиты.

Слой

Что снимает

Когда срабатывает

Кого ловит

TLS (JA3/JA4)

Отпечаток ClientHello

До HTTP-запроса

curl, Python, Go, стоковый headless

HTTP/2

Akamai h2 fingerprint

До отдачи контента

Клиентов с рассинхроном TLS и h2

Browser fingerprint

Canvas, WebGL, шрифты

На странице

Headless с подделанным TLS

Поведение + ASN

Мышь, скролл, репутация IP

В сессии

Продвинутые фермы и резидентные прокси

Из нашей практики: чаще всего бот палится не на самом JA4, а на рассинхроне между слоями — TLS говорит «Chrome», а HTTP/2-отпечаток или отсутствие Canvas выдают автоматизацию. Одиночный сигнал подделать реально, согласованность всех слоёв сразу — почти нет.

Такой многослойный подход и даёт заявленные 99.9% точности: дешёвых ботов мы рубим на TLS без нагрузки, дорогих — на поведении и браузерном отпечатке. Ни один слой не идеален по отдельности — сила именно в комбинации сигналов.

Многослойная защита: TLS + ASN + поведение + браузерный отпечаток в одном risk-score. Посмотреть тарифы →

Часто задаваемые вопросы

Что такое JA3-отпечаток простыми словами?

JA3-отпечаток — это короткий идентификатор TLS-клиента, вычисленный из полей пакета ClientHello (версия TLS, шифры, расширения, кривые) и свёрнутый в 32-символьный MD5-хеш. По нему видно, какой программой установлено соединение: браузером, curl, Python-скриптом или ботом.

Чем JA4 отличается от JA3?

JA4 сортирует TLS-расширения и шифры перед хешированием, поэтому устойчив к рандомизации порядка расширений, которую Chrome ввёл в 2023 году. Также JA4 использует SHA-256 вместо MD5, поддерживает QUIC/HTTP3 и имеет читаемый трёхчастный формат a_b_c. По сути это преемник JA3, который к 2026 году стал отраслевым стандартом.

Можно ли подделать JA3-отпечаток?

Да, но это сложнее, чем подделать HTTP-заголовки. Инструменты вроде curl-impersonate, utls и curl_cffi пересобирают TLS-стек так, чтобы ClientHello совпадал с браузерным. Поэтому TLS-fingerprinting не используют в одиночку — его комбинируют с поведенческим анализом и browser fingerprint, которые подделать одновременно куда труднее.

Почему у моего браузера меняется JA3-отпечаток?

С Chrome 110 (январь 2023) браузер случайно перемешивает порядок TLS-расширений при каждом соединении — это даёт триллионы вариантов JA3 для одного браузера. Именно поэтому классический JA3 стал ненадёжным для идентификации браузеров, и индустрия перешла на JA4, который к порядку расширений нечувствителен.

Виден ли JA3, ведь HTTPS-трафик зашифрован?

Да, виден. Пакет ClientHello отправляется в открытом виде в самом начале TLS-рукопожатия — до того как поднимется шифрованный канал. Поэтому сервер и антибот-сервис читают параметры клиента и снимают JA3 ещё до передачи любых зашифрованных данных и до первого HTTP-заголовка.

Заменяет ли TLS-fingerprinting капчу?

Частично. TLS-отпечаток отсекает простых ботов автоматически и без фрикшена для пользователя — в отличие от капчи, которую видят все. Но против продвинутых ботов с подделанным ClientHello нужны дополнительные слои. В связке с поведенческой аналитикой TLS-fingerprinting позволяет отказаться от капчи для большинства посетителей.

Работает ли JA3 против headless-браузеров?

Против стокового Puppeteer или Playwright с системным Chromium — да: их TLS-окружение и отпечаток отличаются от обычного браузера. Но если headless запущен на настоящем Chrome с патчами маскировки, JA3 может совпасть с браузерным. Поэтому headless-ботов ловят связкой TLS-отпечатка, browser fingerprinting и поведенческого анализа, а не одним JA3.

Как проверить свой JA3/JA4-отпечаток?

Есть публичные сервисы, которые показывают ваш JA3 и JA4 при заходе (например, tls.browserleaks.com и аналоги). Откройте такой сервис в разных браузерах и в curl — увидите, что отпечатки различаются. Это наглядно демонстрирует, почему по TLS-рукопожатию бот отличается от настоящего браузера.

О BotHunt

BotHunt — российский сервис защиты сайтов от поведенческих ботов, парсеров, спама и брутфорса. Подключается через DNS (без изменений на сервере) или одной строкой кода — плагином для WordPress, PHP-агентом или через Bitrix/OpenCart. Срабатывает в реальном времени и блокирует ботов до того, как они попадут в Метрику и повлияют на позиции в Яндексе. Точность детекции — 99,9%, ложных срабатываний — менее 0,05%.

Начать
14 дней бесплатно