5 методов определения браузера через JavaScript: от классики до тестов

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Фронтенд-разработчики
  • Тестировщики и 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. Это строка, содержащая информацию о браузере, операционной системе и другие детали клиента.

Базовый пример использования:

JS
Скопировать код
const userAgentString = navigator.userAgent;
console.log(userAgentString);

Пример вывода для Chrome:

JS
Скопировать код
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:

JS
Скопировать код
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:

JS
Скопировать код
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: Использование регулярных выражений

JS
Скопировать код
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, которые могут предоставить более структурированную информацию:

JS
Скопировать код
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), которая предоставляет подробную информацию о браузере, его версии и типе устройства.

Установка:

Bash
Скопировать код
# npm
npm install bowser

# yarn
yarn add bowser

Базовое использование:

JS
Скопировать код
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():

json
Скопировать код
{
name: "Chrome",
version: "91.0.4472.124"
}

Преимущества Bowser:

  • Маленький размер (≈5 KB)
  • Не имеет зависимостей
  • Поддерживает семантическое сравнение версий
  • Регулярно обновляется для поддержки новых браузеров
  • Работает как в браузере, так и в Node.js

Detector.js: гибкость и расширяемость

Detector.js — это более функциональная библиотека, которая не только определяет браузер, но и предоставляет информацию о поддерживаемых функциях.

Установка:

Bash
Скопировать код
npm install detectorjs

Базовое использование:

JS
Скопировать код
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:

JS
Скопировать код
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

Базовый пример проверки поддержки функций:

JS
Скопировать код
// Проверка поддержки 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:

Bash
Скопировать код
# Установка
npm install modernizr

В HTML добавляем скрипт Modernizr:

HTML
Скопировать код
<script src="path/to/modernizr.js"></script>

Проверка поддержки функций:

JS
Скопировать код
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 для большинства случаев с определением браузера для специфических проблем, связанных с конкретными браузерами.

JS
Скопировать код
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 для функциональности и определение браузера для аналитики и работы со специфическими багами.

Загрузка...