Большинство систем защиты смотрят на 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. Порядок полей фиксирован, значения записываются в десятичном виде: поля разделяются запятыми, значения внутри поля — дефисами.

Поле | Что содержит | Пример значения |
|---|---|---|
Версия 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-заголовков ещё физически невозможна.

Порядок установки соединения выглядит так:
Клиент открывает TCP-соединение с сервером.
TLS handshake: клиент шлёт ClientHello в plaintext — здесь и снимается JA3.
Стороны согласуют ключи и поднимают шифрованный канал.
Только теперь уходит 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, который перемешивает порядок.

Что изменилось в 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-сигнал не выносит вердикт сам по себе.
Как это устроено по шагам:
На edge-узле, до вашего сервера, мы читаем ClientHello и считаем JA3/JA4. Это занимает доли миллисекунды.
Отпечаток сверяется с базой известных ботов и с ожидаемым для заявленного User-Agent. Рассинхрон вида «UA=Chrome, а JA4=Python» — сильный сигнал бота.
TLS-результат суммируется с ASN-репутацией (дата-центр против домашнего IP), поведением на странице и отпечатком браузера в единый risk-score.
Итоговое решение — пропустить, показать челлендж или заблокировать — принимается менее чем за 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-рукопожатию бот отличается от настоящего браузера.




