5 методов определения браузера через JavaScript: от классики до тестов
Для кого эта статья:
- Фронтенд-разработчики
- Тестировщики и QA-инженеры
Студенты и начинающие специалисты в области веб-разработки
Привет, фронтендеры и тестировщики! 👋 Сталкивались с ситуацией, когда ваш код прекрасно работает в Chrome, но ломается в Safari? Или когда пользователи жалуются на странное поведение интерфейса в Firefox, а у вас всё отображается идеально? Определение версии браузера — тот технический аспект, который может спасти вас от головной боли при отладке и существенно упростить тестирование. Сегодня разберём 5 надежных методов идентификации браузера через JavaScript, от классики до современных подходов.
Хотите уверенно решать задачи кроссбраузерной совместимости и писать код, который работает везде? Курс Обучение веб-разработке от Skypro погружает вас в реальные проекты с первого месяца. Вы не просто изучаете теорию определения браузеров, а сразу применяете знания на практике, создавая адаптивные веб-приложения под руководством опытных менторов, которые помогают избежать типичных ошибок новичков.
Почему важно определять браузер: проблемы совместимости
Определение браузера пользователя — не прихоть разработчиков, а необходимость, продиктованная разнообразием браузерных движков и их интерпретацией веб-стандартов. Даже сегодня, когда стандартизация продвинулась далеко вперёд, существуют серьёзные различия между браузерами.
Алексей Петров, ведущий фронтенд-разработчик Однажды мы запустили сервис онлайн-бронирования с использованием новейших CSS Grid Layout функций. В Chrome всё работало безупречно — сетка адаптировалась, элементы располагались именно так, как задумано. Однако через неделю после запуска посыпались жалобы от клиентов: "Не могу забронировать номер, кнопка не отображается".
Анализ показал, что 23% пользователей заходили с Safari на macOS, где поддержка некоторых CSS-свойств отличалась. Мы срочно внедрили определение браузера и версии, создав альтернативную вёрстку для проблемных браузеров. Конверсия моментально вернулась к плановым показателям. Эта ситуация наглядно показала, почему детектирование браузера — не просто техническая деталь, а бизнес-необходимость.
Основные сценарии, где критично определение браузера:
- API-несовместимость — некоторые JavaScript API доступны только в определённых браузерах (например, Push API, Background Sync)
- CSS-рендеринг — браузеры по-разному интерпретируют некоторые CSS-свойства, особенно новые
- Оптимизация производительности — разные браузеры требуют разных подходов к оптимизации
- Безопасность — некоторые уязвимости специфичны для конкретных версий браузеров
- Аналитика использования — полезно знать, какие браузеры используют ваши пользователи
| Браузер | Движок рендеринга | JavaScript движок | Типичные проблемы |
|---|---|---|---|
| Chrome | Blink | V8 | Экспериментальные функции часто меняются |
| Firefox | Gecko | SpiderMonkey | Отличия в работе с CSS Grid и Flexbox |
| Safari | WebKit | JavaScriptCore | Отставание в поддержке новых Web API |
| Edge (новый) | Blink | V8 | Проблемы с Windows-специфичными функциями |
| IE 11 | Trident | Chakra | Отсутствие поддержки современных стандартов |

Navigator.userAgent: основной метод идентификации браузера
Самый распространённый метод определения браузера — использование свойства navigator.userAgent. Это строка, содержащая информацию о браузере, операционной системе и другие детали клиента.
Базовый пример использования:
const userAgentString = navigator.userAgent;
console.log(userAgentString);
Пример вывода для Chrome:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Для Safari на iPhone:
Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
Определение основных браузеров через userAgent:
function detectBrowser() {
const userAgent = navigator.userAgent;
// Определяем браузер
if (userAgent.indexOf("Firefox") > -1) {
return "Firefox";
} else if (userAgent.indexOf("SamsungBrowser") > -1) {
return "Samsung Browser";
} else if (userAgent.indexOf("Opera") > -1 || userAgent.indexOf("OPR") > -1) {
return "Opera";
} else if (userAgent.indexOf("Trident") > -1) {
return "Internet Explorer";
} else if (userAgent.indexOf("Edge") > -1) {
return "Microsoft Edge (Legacy)";
} else if (userAgent.indexOf("Edg") > -1) {
return "Microsoft Edge (Chromium)";
} else if (userAgent.indexOf("Chrome") > -1) {
return "Chrome";
} else if (userAgent.indexOf("Safari") > -1) {
return "Safari";
} else {
return "Unknown";
}
}
console.log("Вы используете: " + detectBrowser());
Преимущества метода navigator.userAgent:
- Доступен во всех браузерах без дополнительных библиотек
- Содержит подробную информацию о версии и платформе
- Исторически проверенный подход
Недостатки метода:
- Строка userAgent легко подделывается
- Формат может меняться без предупреждения
- Сложность парсинга из-за неструктурированного формата
- Некоторые браузеры намеренно маскируются под другие
Марина Соколова, QA-инженер по автоматизации При разработке фреймворка для автотестирования я столкнулась с проблемой: нужно было запускать разные тесты в зависимости от браузера. Для Chrome у нас был один набор тестов, для Firefox — другой, а Safari требовал особого подход.
Первоначально мы использовали простой подход с проверкой navigator.userAgent. Всё работало до того момента, пока мы не начали тестировать на WebView в мобильных приложениях. Оказалось, что userAgent там содержит одновременно "Chrome" и "Safari", что ломало нашу логику распознавания.
Мы перешли на более сложную систему определения с использованием регулярных выражений и дополнительных проверок возможностей браузера. Такой гибридный подход позволил точно идентифицировать даже проблемные случаи вроде WebView и старых версий Edge. Время отладки тестов сократилось на 40%, потому что мы перестали получать ложные срабатывания из-за неверного определения браузера.
Парсинг userAgent строки: извлекаем точную версию
Простое определение типа браузера не всегда достаточно — часто требуется узнать точную версию, особенно когда функциональность различается между минорными релизами. Для этого необходимо парсить строку userAgent и извлекать нужную информацию.
Рассмотрим несколько подходов к парсингу, начиная с простых решений и заканчивая более сложными.
Метод 1: Использование регулярных выражений
function getBrowserInfo() {
const userAgent = navigator.userAgent;
let browserName;
let browserVersion;
// Chrome
if (/Chrome/.test(userAgent) && !/Chromium|Edge|Edg|OPR|SamsungBrowser/.test(userAgent)) {
browserName = "Chrome";
browserVersion = userAgent.match(/Chrome\/(\d+\.\d+)/)[1];
}
// Firefox
else if (/Firefox/.test(userAgent)) {
browserName = "Firefox";
browserVersion = userAgent.match(/Firefox\/(\d+\.\d+)/)[1];
}
// Safari
else if (/Safari/.test(userAgent) && !/Chrome/.test(userAgent)) {
browserName = "Safari";
browserVersion = userAgent.match(/Version\/(\d+\.\d+)/)[1];
}
// Edge (Chromium-based)
else if (/Edg/.test(userAgent)) {
browserName = "Microsoft Edge";
browserVersion = userAgent.match(/Edg\/(\d+\.\d+)/)[1];
}
// Edge (Legacy)
else if (/Edge/.test(userAgent)) {
browserName = "Microsoft Edge (Legacy)";
browserVersion = userAgent.match(/Edge\/(\d+\.\d+)/)[1];
}
// Internet Explorer
else if (/Trident/.test(userAgent)) {
browserName = "Internet Explorer";
// IE 11 не имеет явного указания версии в userAgent
browserVersion = userAgent.match(/rv:(\d+\.\d+)/) ? userAgent.match(/rv:(\d+\.\d+)/)[1] : "11.0";
}
// Opera
else if (/OPR/.test(userAgent) || /Opera/.test(userAgent)) {
browserName = "Opera";
browserVersion = userAgent.match(/(?:OPR|Opera)\/(\d+\.\d+)/)[1];
} else {
browserName = "Unknown";
browserVersion = "0.0";
}
return {
name: browserName,
version: browserVersion
};
}
const browser = getBrowserInfo();
console.log(`Браузер: ${browser.name} ${browser.version}`);
Метод 2: Использование встроенных объектов navigator
В современных браузерах доступны дополнительные свойства объекта navigator, которые могут предоставить более структурированную информацию:
function getModernBrowserInfo() {
// Проверяем поддержку navigator.userAgentData (современный API)
if (navigator.userAgentData) {
// Получаем базовую информацию
const brands = navigator.userAgentData.brands;
const platform = navigator.userAgentData.platform;
console.log("Платформа:", platform);
// Проходим по всем брендам и ищем реальный браузер
for (const brand of brands) {
// Исключаем служебные бренды
if (brand.brand !== "Not A;Brand") {
console.log(`Браузер: ${brand.brand}, версия: ${brand.version}`);
}
}
// Можно получить более детальную информацию через метод getHighEntropyValues
navigator.userAgentData.getHighEntropyValues(['architecture', 'model', 'platformVersion', 'fullVersionList'])
.then(ua => {
console.log("Полная версия браузера:", ua.fullVersionList);
console.log("Архитектура:", ua.architecture);
console.log("Устройство:", ua.model);
console.log("Версия ОС:", ua.platformVersion);
});
} else {
// Для браузеров, не поддерживающих userAgentData
console.log("navigator.userAgentData не поддерживается в этом браузере");
// Используем fallback на userAgent
return getBrowserInfo(); // метод из предыдущего примера
}
}
Сравнение методов парсинга userAgent:
| Метод | Преимущества | Недостатки | Совместимость |
|---|---|---|---|
| Простые условия по подстроке | Легко реализовать | Низкая точность, не определяет версию | Все браузеры |
| Регулярные выражения | Точное определение версии | Сложный код, требует поддержки | Все браузеры |
| navigator.userAgentData | Структурированные данные, высокая точность | Ограниченная поддержка браузерами | Chrome 89+, Edge 89+ |
| Библиотеки (UA-parser.js) | Готовое решение, хорошая точность | Зависимость от внешнего кода | Все браузеры |
Библиотеки для определения браузера: Bowser и Detector.js
Ручной парсинг userAgent может быть трудоёмким и подверженным ошибкам процессом. К счастью, существуют специализированные библиотеки, которые значительно упрощают эту задачу. Рассмотрим две популярные библиотеки для определения браузера: Bowser и Detector.js.
Bowser: легковесный и точный парсер
Bowser — это легковесная библиотека (около 5 KB), которая предоставляет подробную информацию о браузере, его версии и типе устройства.
Установка:
# npm
npm install bowser
# yarn
yarn add bowser
Базовое использование:
import Bowser from 'bowser';
const browserInfo = Bowser.getParser(window.navigator.userAgent);
// Получение базовой информации
console.log(browserInfo.getBrowser());
console.log(browserInfo.getOS());
console.log(browserInfo.getPlatform());
// Проверка определённой версии браузера
if(browserInfo.satisfies({chrome: '>88'})) {
console.log('Функция доступна в вашем браузере');
} else {
console.log('Обновите браузер для использования этой функции');
}
Пример вывода метода getBrowser():
{
name: "Chrome",
version: "91.0.4472.124"
}
Преимущества Bowser:
- Маленький размер (≈5 KB)
- Не имеет зависимостей
- Поддерживает семантическое сравнение версий
- Регулярно обновляется для поддержки новых браузеров
- Работает как в браузере, так и в Node.js
Detector.js: гибкость и расширяемость
Detector.js — это более функциональная библиотека, которая не только определяет браузер, но и предоставляет информацию о поддерживаемых функциях.
Установка:
npm install detectorjs
Базовое использование:
import Detector from 'detectorjs';
const detector = new Detector(window.navigator.userAgent);
// Получение информации о браузере
console.log(detector.browser.name); // "Chrome"
console.log(detector.browser.version); // "91.0.4472.124"
// Информация об OS
console.log(detector.os.name); // "Windows"
console.log(detector.os.version); // "10"
// Проверка типа устройства
console.log(detector.device.type); // "desktop"
Особенности Detector.js:
- Определение не только браузера, но и железа
- Расширяемая архитектура с возможностью добавления кастомных детекторов
- Подробная информация о мобильных устройствах
- Возможность определения ботов и краулеров
Сравнение библиотек:
| Библиотека | Размер (min+gzip) | Точность определения | Особенности | Лучший сценарий использования |
|---|---|---|---|---|
| Bowser | ≈5 KB | Высокая | Семантическое сравнение версий, легковесность | Когда критичен размер бандла |
| Detector.js | ≈12 KB | Очень высокая | Расширяемость, определение устройств | Для сложных условий с множеством правил |
| UAParser.js | ≈6 KB | Высокая | Кроссплатформенность, поддержка Node.js | Когда нужно определение и на клиенте, и на сервере |
| Platform.js | ≈4 KB | Средняя | Фокус на платформе, а не на браузере | Когда важнее определить OS, чем браузер |
Пример интеграции Bowser с Feature Detection:
import Bowser from 'bowser';
function initializeApplication() {
const browser = Bowser.getParser(window.navigator.userAgent);
// Проверка поддержки необходимых функций для полной версии
if (browser.satisfies({
chrome: ">80",
firefox: ">75",
safari: ">13",
edge: ">80"
})) {
loadFullVersion();
}
// Safari на iOS требует особого подхода к некоторым API
else if (browser.getBrowserName() === 'Safari' && browser.getPlatformType() === 'mobile') {
loadIOSOptimizedVersion();
}
// Для старых браузеров загружаем облегченную версию
else {
loadLegacyVersion();
}
// Дополнительная проверка функций независимо от браузера
if (!window.IntersectionObserver) {
loadIntersectionObserverPolyfill();
}
}
initializeApplication();
Feature detection вместо User-Agent: современный подход
Определение браузера по User-Agent постепенно уступает место более надёжному подходу — Feature Detection (определению возможностей). Вместо того, чтобы пытаться узнать конкретный браузер и его версию, современные разработчики предпочитают проверять поддержку конкретных функций, которые нужны для работы приложения. 🔍
Почему Feature Detection лучше User-Agent?
- Устойчивость к изменениям: даже если браузер изменит формат User-Agent, ваш код продолжит работать
- Точность: вы проверяете именно те функции, которые вам нужны, а не полагаетесь на информацию о версии
- Прогрессивное улучшение: легче реализовать стратегию, когда базовая функциональность доступна всем, а продвинутые возможности только поддерживающим браузерам
- Независимость от спуфинга: некоторые браузеры маскируются под другие через User-Agent, но не могут подделать наличие или отсутствие API
Как реализовать Feature Detection
Базовый пример проверки поддержки функций:
// Проверка поддержки Fetch API
if (window.fetch) {
// Используем fetch
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
} else {
// Fallback на XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data');
xhr.onload = function() {
if (xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send();
}
// Проверка поддержки WebP
function checkWebPSupport() {
return new Promise(resolve => {
const webP = new Image();
webP.onload = webP.onerror = function() {
resolve(webP.height === 2);
};
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
});
}
checkWebPSupport().then(hasSupport => {
if (hasSupport) {
console.log('WebP поддерживается');
// Загружаем WebP изображения
} else {
console.log('WebP не поддерживается');
// Загружаем JPEG или PNG изображения
}
});
Modernizr: библиотека для Feature Detection
Modernizr — популярная библиотека, которая упрощает Feature Detection и предоставляет единый API для проверки множества функций.
Использование Modernizr:
# Установка
npm install modernizr
В HTML добавляем скрипт Modernizr:
<script src="path/to/modernizr.js"></script>
Проверка поддержки функций:
if (Modernizr.webp) {
// Поддержка WebP
loadWebPImages();
} else {
// Нет поддержки WebP
loadJpegImages();
}
if (Modernizr.flexbox) {
// Используем Flexbox для лейаута
enableFlexboxLayout();
} else {
// Fallback на float или другой подход
enableLegacyLayout();
}
// Проверка нескольких функций
if (Modernizr.cssgrid && Modernizr.flexgap) {
// Полная поддержка современных сеток
enableAdvancedLayout();
} else if (Modernizr.cssgrid) {
// Есть Grid, но нет gap
enableGridWithoutGap();
} else {
// Нет поддержки Grid
enableFallbackLayout();
}
Гибридный подход: сочетание определения браузера и Feature Detection
В реальных проектах часто используется гибридный подход, сочетающий Feature Detection для большинства случаев с определением браузера для специфических проблем, связанных с конкретными браузерами.
import Bowser from 'bowser';
// Определяем браузер для сбора аналитики
const browser = Bowser.getParser(window.navigator.userAgent);
const browserInfo = {
name: browser.getBrowserName(),
version: browser.getBrowserVersion(),
os: browser.getOSName()
};
// Отправляем данные о браузере в аналитику
sendAnalytics('browser_info', browserInfo);
// Используем Feature Detection для фактической функциональности
function initApp() {
// Проверка поддержки основных API
const supports = {
serviceWorker: 'serviceWorker' in navigator,
webp: false, // Будет определено асинхронно
webgl: (function() {
try {
return !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl');
} catch(e) {
return false;
}
})(),
touchEvents: 'ontouchstart' in window,
passiveEvents: (function() {
let supportsPassive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
return true;
}
});
window.addEventListener('testpassive', null, opts);
window.removeEventListener('testpassive', null, opts);
} catch (e) {}
return supportsPassive;
})()
};
// Проверяем поддержку WebP асинхронно
checkWebPSupport().then(hasSupport => {
supports.webp = hasSupport;
// Safari на iOS имеет баг с определенными API даже если Feature Detection показывает поддержку
const isSafariIOS = browser.getBrowserName() === 'Safari' && browser.getOSName() === 'iOS';
if (isSafariIOS && supports.serviceWorker) {
// Известная проблема с Service Worker в Safari iOS
console.warn('Safari iOS имеет проблемы с Service Worker');
// Специфичный workaround для Safari iOS
}
// Инициализируем приложение с учетом поддерживаемых функций
initializeWithFeatures(supports);
});
}
initApp();
Технология определения браузера — это не просто технический инструмент, а стратегический подход к разработке. Выбирая между прямым определением браузера через userAgent, использованием специализированных библиотек или Feature Detection, вы принимаете решение о будущей устойчивости вашего кода. Современный подход с фокусом на возможностях, а не названиях браузеров, делает ваше приложение более адаптивным к изменениям веб-ландшафта и новым технологиям. Как показывает практика, комбинирование методов дает наилучшие результаты — используйте Feature Detection для функциональности и определение браузера для аналитики и работы со специфическими багами.