User-Agent

29 сентября 2026 · ~14 мин чтения

протокол веб http боты аналитика

User-Agent

User-Agent — это заголовок HTTP-запроса, в котором клиент (браузер, приложение, робот, скрипт) сам сообщает серверу, кто он такой: название программы, версию, движок, иногда операционную систему и устройство. Это самопредставление, а не удостоверение личности: сервер получает ровно то, что клиент решил написать.

История

Слово «user agent» (агент пользователя) старше веба. В инженерных стандартах так называют программу, которая действует от имени человека: почтовый клиент — это mail user agent (MUA), браузер — web user agent. Идея простая: между человеком и сетью стоит посредник, и у посредника есть имя.

1990–1996: рождение заголовка. Первая версия HTTP (её потом назвали HTTP/0.9), которую Тим Бернерс-Ли запустил в CERN в 1990–1991 годах, вообще не имела заголовков — запрос состоял из одной строки GET /page. Заголовки появились по мере того, как протокол обрастал возможностями, и в мае 1996 года вышел RFC 1945 (HTTP/1.0, авторы — Тим Бернерс-Ли, Рой Филдинг, Хенрик Фристик Нильсен). В нём заголовок User-Agent описан официально: «для статистических целей, отслеживания нарушений протокола и автоматического распознавания клиентов, чтобы подстраивать ответ». Заметь: уже тогда в стандарт заложили оба применения — и аналитику, и подстройку контента.

1993–1995: браузерные войны и «Mozilla». Самый смешной и поучительный кусок истории. Браузер NCSA Mosaic (1993) представлялся как NCSA_Mosaic/2.0 (Windows 3.1). Затем появился Netscape Navigator, внутреннее кодовое имя которого было Mozilla («Mosaic killer», убийца Мозаика). Он писал Mozilla/1.0 (Win3.1) и поддерживал фреймы, а Mosaic — нет. Сайты начали проверять: «если в UA есть Mozilla — отдаём версию с фреймами». Когда в 1995 году вышел Internet Explorer от Microsoft и тоже умел фреймы, он получал урезанную версию страниц. Решение Microsoft: притвориться. IE стал писать Mozilla/2.0 (compatible; MSIE 3.0; Windows 95). С этого момента заголовок перестал быть честным.

2000-е: матрёшка. Дальше каждый новый браузер наслаивал чужие имена, чтобы его не обделили. Konqueror с движком KHTML писал like Gecko (Gecko — движок Firefox). Apple в 2003 году взяла KHTML, сделала из него WebKit и Safari — и Safari писал AppleWebKit/... (KHTML, like Gecko) Safari/.... Google Chrome (2008) построен на WebKit и добавил себя сверху. Поэтому сегодняшний Chrome на Android выглядит примерно так:

Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/129.0.0.0 Mobile Safari/537.36

В одной строке упомянуты пять разных браузеров, и только один из них — правда. Эту историю хорошо рассказал Аарон Андерсен в заметке «History of the browser user-agent string» (2008) — её до сих пор цитируют.

2020–2023: заморозка. Длинный и подробный UA оказался подарком для fingerprinting (отпечатка браузера — идентификации человека без cookie по совокупности признаков). В 2020 году Google объявил программу User-Agent Reduction: в Chrome примерно с версий 101–113 (2022–2023) из строки постепенно убрали точную версию ОС, модель устройства и минорную версию браузера. Отсюда буква K вместо модели телефона и вечный Android 10 в примере выше. Взамен — механизм User-Agent Client Hints (о нём ниже). Safari и Firefox тоже заморозили часть полей. Актуальный стандарт HTTP-семантики — RFC 9110 (2022), раздел 10.1.5, — описывает User-Agent и прямо предупреждает о рисках для приватности.

Что это такое

Технически User-Agent — одна строка текста в заголовках запроса. Её отправляет клиент при каждом обращении к серверу: за HTML-страницей, картинкой, скриптом, API-ответом. Формат рекомендован стандартом: последовательность «продуктов» вида имя/версия, между ними — комментарии в скобках. Например, curl/8.7.1, python-requests/2.32.3, YandexBot/3.0.

Ключевое свойство: строку формирует клиент, и сервер никак не может её проверить. Браузер пишет её честно (со всеми историческими масками), библиотеки пишут своё имя по умолчанию, а любой скрипт может подставить что угодно одной строкой кода. Поэтому User-Agent — это заявление, а не факт.

Кто и зачем читает UA:

Похожие вещи, с которыми его путают:

Аналогии из жизни

Бейдж на конференции. Каждый участник сам вписывает имя и компанию в бейдж, и организаторы по бейджу решают, пускать ли в VIP-зону. Работает: люди в основном пишут правду, и по бейджам удобно считать, кто пришёл. Где ломается: на конференции есть регистрация с паспортом до выдачи бейджа, а в HTTP никакой регистрации нет — бейдж пишут на входе маркером, и никто не сверяет. Плюс в вебе все участники исторически пишут на бейдже «Mozilla», чтобы их пустили: представь конференцию, где у каждого второго на бейдже стоит имя самого популярного спикера.

Акцент по телефону. Звонишь в службу поддержки, оператор по речи понимает, что ты из другого региона, и переключает на подходящую линию. Работает: сервер действительно по «манере представления» подстраивает ответ. Где ломается: акцент сложно подделать, а UA — одна строка. И акцент не меняется от звонка к звонку, а UA меняется с каждым обновлением браузера — логика вида «если версия ровно такая-то» устаревает за месяцы.

Этикетка на банке. На складе ящики сортируют по надписи на этикетке, не вскрывая. Быстро и почти всегда верно. Где ломается: если кто-то переклеит этикетку, склад отправит ящик не туда — ровно так боты с «браузерным» UA проходят через фильтры, настроенные только на UA. Честная сортировка требует хотя бы выборочно вскрывать ящики — в вебе это проверка IP, поведения, выполнения JavaScript.

Как это работает

Разберём путь одного запроса.

Шаг 1. Клиент собирает строку. Браузер формирует UA из зашитого шаблона: платформа, движок, версия. Библиотеки делают проще: curl шлёт curl/<версия>, Python-библиотека requests — python-requests/<версия>, а голый urllib — Python-urllib/3.x. Программист может переопределить заголовок одной строкой.

Шаг 2. Запрос уходит на сервер.

GET /go?campaign=42 HTTP/1.1
Host: example.ru
User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36
Accept: text/html

В HTTP/2 и HTTP/3 заголовок передаётся в сжатом бинарном виде, но смысл тот же.

Шаг 3. Сервер разбирает строку. Обычно — поиском подстрок или регулярными выражениями (шаблонами текста): «есть Android и есть Chrome/ — значит Chrome на Android», «есть iPhone — iOS». Для серьёзного разбора есть готовые парсеры: открытые (ua-parser с портами на разные языки, ua-parser-js) и коммерческие базы устройств (DeviceAtlas, 51Degrees, WURFL). Порядок проверок критичен: Chrome на iOS содержит CriOS, Firefox на iOS — FxiOS, а оба при этом содержат Safari и работают на WebKit.

Шаг 4. Сервер принимает решение. Типичные ветки:

если UA похож на робота (YandexBot, Googlebot) -> отдать обычную HTML-страницу
иначе если мобильный Android-браузер -> отдать ссылку на приложение (intent://)
иначе если iOS -> отдать универсальную ссылку
иначе -> обычная веб-страница

Шаг 5. Ответ помечается заголовком Vary: User-Agent. Это подсказка кэшам и CDN (сетям доставки контента): «ответ зависит от UA, не отдавай десктопную версию мобильному». Без этого кэш может перемешать варианты. Минус — кэш дробится на тысячи вариантов, поэтому CDN часто нормализуют UA до пары «мобильный/десктоп».

Шаг 6. Строка попадает в лог. Стандартный формат логов nginx и Apache (combined) пишет UA в конце строки. Именно по логам потом отвечают на вопросы «сколько ботов», «какие браузеры» и «приходил ли вообще такой клиент».

Client Hints — как это выглядит. Браузер на Chromium по умолчанию шлёт:

Sec-CH-UA: "Chromium";v="129", "Not=A?Brand";v="8"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Platform: "Android"

Строка Not=A?Brand — нарочно абсурдная (GREASE — «смазка» протокола): её добавляют, чтобы сайты не писали хрупких проверок «ровно этот список брендов». Если серверу нужна модель устройства, он отвечает заголовком Accept-CH: Sec-CH-UA-Model, и следующие запросы её уже содержат. Firefox и Safari на момент написания Client Hints в таком виде не поддерживают — точно проверь на caniuse.com по запросу «User-Agent Client Hints».

UA — не доказательство

Любое решение, которое даёт доступ, деньги или доверие, не может опираться только на User-Agent. Бот пишет Chrome за одну строку кода, а настоящий робот поисковика проверяется по IP: обратный DNS-запрос должен вернуть домен поисковика, а прямой — тот же IP.

Как проверить робота всерьёз. И Google, и Яндекс официально описывают одну и ту же процедуру: взять IP запроса, сделать обратный DNS-запрос (PTR), убедиться, что имя оканчивается на домен поисковика (googlebot.com, google.com, yandex.ru, yandex.net, yandex.com), затем сделать прямой запрос по этому имени и убедиться, что вернулся тот же IP. Google дополнительно публикует списки IP-диапазонов своих роботов в JSON.

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Отсутствие — тоже данные

Самые полезные выводы по UA часто негативные: «за две недели с IP поисковика не было ни одного запроса с мобильным Android-UA» опровергает гипотезу надёжнее, чем любые рассуждения о том, как робот должен себя вести.

Кто пользуется

Альтернативы и конкуренты

User-Agent Client Hints.
Плюсы: структурированные поля, меньше утечка данных по умолчанию, не нужно парсить исторический мусор.
Минусы: поддерживаются в основном браузерами на Chromium; подробности приходят только со второго запроса после Accept-CH.

Feature detection (проверка возможностей) на клиенте.
Плюсы: проверяешь не «какой браузер», а «умеет ли он нужное» ('serviceWorker' in navigator) — надёжно и не устаревает.
Минусы: работает только в JavaScript на странице, сервер на первом запросе этого не знает.

CSS media queries и адаптивная вёрстка.
Плюсы: одна страница сама подстраивается под экран, не нужно угадывать устройство.
Минусы: не решает задач уровня сервера — редирект в приложение или выдачу разных данных.

Проверка по IP и обратному DNS / fingerprinting.
Плюсы: гораздо сложнее подделать, годится для верификации роботов и антибота.
Минусы: дороже в реализации, fingerprinting упирается в приватность и законодательство о персональных данных.

Когда НЕ стоит использовать

Связанные понятия

Литература и источники

Где встретилось у меня

В одном моём проекте рекламный подрядчик предположил, что модерация рекламной системы не может открыть посадочную, потому что редирект отдаёт мобильным ссылку на приложение. Разбор кода и логов показал: такая ссылка выдаётся только при Android-UA с Chrome, а с IP поисковика за две недели таких запросов не было — гипотеза снялась. В тот же день UA всплыл и в задаче по защите квизов от спама как один из сигналов антибота.

Попробуй сам

Выполни curl -sI -A "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" https://example.ru/ и сравни ответ с обычным запросом из браузера. Если твой сайт отвечает по-разному — стоит понять, почему.

Краткое резюме