bowser vs detect-browser vs platform vs ua-parser-js vs universal-user-agent vs user-agent
User-Agent Parsing and Browser Detection in JavaScript
bowserdetect-browserplatformua-parser-jsuniversal-user-agentuser-agentSimilar Packages:

User-Agent Parsing and Browser Detection in JavaScript

These libraries help developers identify the browser, operating system, and device from a user-agent string. This is critical for handling compatibility issues, applying specific CSS fixes, or adjusting server-side rendering logic. While modern web development encourages feature detection over browser sniffing, there are still valid cases where knowing the client environment is necessary for analytics, security, or progressive enhancement.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
bowser05,728258 kB86a month agoMIT
detect-browser069927 kB464 years agoMIT
platform03,243-346 years agoMIT
ua-parser-js010,0761.31 MB21a month agoAGPL-3.0-or-later
universal-user-agent02210.1 kB010 months agoISC
user-agent0-----

User-Agent Parsing and Browser Detection in JavaScript

Identifying the client environment is a common requirement in web development. Whether you are debugging a CSS issue specific to Safari, blocking outdated browsers for security, or simply collecting analytics, you need to parse the user-agent string. The ecosystem offers several tools for this, ranging from lightweight detectors to comprehensive parsers. Let's compare how bowser, detect-browser, platform, ua-parser-js, universal-user-agent, and user-agent handle this task.

🧩 Parsing Depth: Basic Info vs Full Device Profile

The level of detail you get varies significantly between these libraries. Some focus only on the browser name, while others extract device models and OS versions.

bowser provides a balanced set of data, covering browser, OS, and device type.

import bowser from 'bowser';

const browser = bowser.getParser(navigator.userAgent);
const browserName = browser.getBrowserName();
const isMobile = browser.is('mobile');

console.log(browserName); // "Chrome"
console.log(isMobile);    // true/false

detect-browser focuses on the browser itself, returning name, version, and OS.

import { detect } from 'detect-browser';

const browser = detect();

if (browser) {
  console.log(browser.name);    // "chrome"
  console.log(browser.version); // "80.0.3987.149"
  console.log(browser.os);      // "Mac OS"
}

platform offers detailed platform data, including layout engine and description.

import platform from 'platform';

console.log(platform.name);    // "Chrome"
console.log(platform.version); // "80.0.3987.149"
console.log(platform.layout);  // "Blink"
console.log(platform.toString()); // "Chrome 80.0.3987.149 on Mac OS"

ua-parser-js gives the most granular control, separating browser, device, and engine objects.

import UAParser from 'ua-parser-js';

const parser = new UAParser(navigator.userAgent);
const result = parser.getResult();

console.log(result.browser.name);    // "Chrome"
console.log(result.device.model);    // "iPhone"
console.log(result.engine.name);     // "WebKit"

universal-user-agent is designed to return a simple string or basic object, often for API headers.

import { getUserAgent } from 'universal-user-agent';

// Typically used in Node or Browser to get a normalized string
const ua = getUserAgent(); 

console.log(ua); // "my-app/1.0.0" or similar normalized string

user-agent is a legacy package that provides basic parsing but lacks modern maintenance.

import userAgent from 'user-agent';

// Legacy callback or sync style depending on version
const info = userAgent.parse(navigator.userAgent);

console.log(info.family); // "Chrome"

🛠️ API Style: Objects vs Functions vs Classes

How you interact with the library affects code readability and integration.

bowser uses a parser instance pattern, which allows for method chaining and clear separation of concerns.

import bowser from 'bowser';

const parser = bowser.getParser(userAgentString);
const isValid = parser.satisfies({ chrome: '>60', firefox: '>50' });

detect-browser uses a simple function call that returns a plain object immediately.

import { detect } from 'detect-browser';

const info = detect();
// Direct property access, no instantiation needed
if (info && info.name === 'ie') { /* ... */ }

platform exposes a single object that is populated upon loading.

import platform from 'platform';

// No function call needed, properties are ready
if (platform.os.family === 'Windows') { /* ... */ }

ua-parser-js relies on a class constructor, offering a stateful parser instance.

import UAParser from 'ua-parser-js';

const parser = new UAParser();
parser.setUA(userAgentString);
const browser = parser.getBrowser();

universal-user-agent exports a direct function for immediate retrieval.

import { getUserAgent } from 'universal-user-agent';

const headerValue = getUserAgent();
// Returns a string suitable for HTTP headers

user-agent typically exports a parse function or object.

import userAgent from 'user-agent';

const result = userAgent.parse(navigator.userAgent);
// Returns an object with browser family and version

🌍 Environment Support: Node.js vs Browser

Not all parsers work everywhere. Some are built specifically for the browser, while others are universal.

bowser is isomorphic. It works in Node.js, browser, and TypeScript projects without extra configuration.

// Works in Node.js server-side rendering
import bowser from 'bowser';
const browser = bowser.getParser(req.headers['user-agent']);

detect-browser is primarily designed for the browser but can run in Node if a user-agent string is passed manually (depending on version).

// Browser default
import { detect } from 'detect-browser';
const browser = detect();

// Node usage often requires passing UA explicitly in newer versions
// const browser = detect(navigator.userAgent); 

platform works in both environments but is often associated with older Node versions.

// Node.js usage
const platform = require('platform');
console.log(platform.name);

ua-parser-js is fully universal and is a common choice for server-side parsing in Node.js.

// Node.js server
const UAParser = require('ua-parser-js');
const parser = new UAParser(req.headers['user-agent']);

universal-user-agent is explicitly built to work across Node and browser, often for API clients.

// Used in GitHub Octokit for both environments
import { getUserAgent } from 'universal-user-agent';
const ua = getUserAgent();

user-agent has limited support for modern Node.js environments and is less reliable for server-side rendering.

// Legacy usage
const ua = require('user-agent');
// May require polyfills in modern Node environments

⚠️ Maintenance and Deprecation Status

Using a maintained library is critical for security and compatibility with new browsers.

bowser is actively maintained and updated for new browser versions. It is safe for new projects.

detect-browser receives updates occasionally. It is stable but check for recent commits before adopting for critical infrastructure.

platform is older. While stable, it does not see frequent updates. Use with caution for cutting-edge browser detection.

ua-parser-js is highly active with frequent releases. It is the industry standard for robust parsing.

universal-user-agent is maintained as part of the Octokit ecosystem. It is reliable for its specific use case but not a general-purpose parser.

user-agent should be considered deprecated for new work. It lacks the active development seen in ua-parser-js or bowser.

📊 Summary Table

PackageParsing DepthAPI StyleEnvironmentMaintenance
bowserBrowser, OS, DeviceParser InstanceUniversal✅ Active
detect-browserBrowser, OS, VersionFunction ReturnBrowser-first⚠️ Moderate
platformBrowser, OS, EngineGlobal ObjectUniversal⚠️ Legacy
ua-parser-jsFull (Device, Engine)Class InstanceUniversal✅ Very Active
universal-user-agentNormalized StringFunctionUniversal✅ Active (Niche)
user-agentBasicFunction/ObjectLimited❌ Deprecated

💡 The Big Picture

ua-parser-js is the heavy-duty choice 🏋️. If you need to know the device model, engine name, or precise versioning for analytics or security, this is the tool. It is the most robust option for server-side rendering.

bowser is the balanced choice ⚖️. It offers a clean API and good coverage without the complexity of ua-parser-js. It is excellent for conditional rendering or feature flags based on browser version.

detect-browser is the quick check ✅. Use it for simple logic like "If IE, show a warning." It is not meant for deep analysis.

universal-user-agent is the specialist 🎯. Keep it for API clients where you need to construct headers, not for analyzing client capabilities.

platform and user-agent are the legacy options 🕰️. Avoid them in new architectures. Existing projects should plan to migrate to bowser or ua-parser-js to ensure future compatibility.

Final Thought: Browser sniffing is fragile. Whenever possible, use feature detection (like checking for fetch or IntersectionObserver). But when you must know the browser, pick a maintained library that fits your depth requirements.

How to Choose: bowser vs detect-browser vs platform vs ua-parser-js vs universal-user-agent vs user-agent

  • bowser:

    Choose bowser if you need a lightweight, promise-free library that works well in both browser and Node.js environments. It is a solid choice for general-purpose parsing where you need to check browser versions without heavy dependencies.

  • detect-browser:

    Choose detect-browser if you want a very simple, synchronous API primarily for browser environments. It is best suited for quick checks where you do not need deep device or OS details, just the browser name and version.

  • platform:

    Choose platform if you are working in a legacy codebase that already relies on it or need specific platform data like layout engine. Note that it is older and less actively maintained than newer alternatives, so evaluate if modern features are required.

  • ua-parser-js:

    Choose ua-parser-js if you need the most detailed parsing results, including device model and vendor. It is widely adopted, supports both Node and browser, and offers a robust API for complex user-agent analysis.

  • universal-user-agent:

    Choose universal-user-agent if you are working within the GitHub Octokit ecosystem or need a simple wrapper that normalizes user-agent strings across Node and browser for API clients. It is more specialized than a general parser.

  • user-agent:

    Avoid user-agent for new projects. This package is largely deprecated or unmaintained compared to active alternatives. Existing projects using it should plan to migrate to ua-parser-js or bowser for better long-term support.

README for bowser

Bowser

A small, fast and rich-API browser/platform/engine detector for both browser and node.

  • Small. Use plain ES5-version which is ~4.8kB gzipped.
  • Optimized. Use only those parsers you need — it doesn't do useless work.
  • Multi-platform. It's browser- and node-ready, so you can use it in any environment.

Don't hesitate to support the project on Github or OpenCollective if you like it ❤️ Also, contributors are always welcome!

Financial Contributors on Open Collective Downloads

Contents

Overview

The library is made to help to detect what browser your user has and gives you a convenient API to filter the users somehow depending on their browsers. Check it out on this page: https://bowser-js.github.io/bowser-online/.

⚠️ Version 2.0 breaking changes ⚠️

Version 2.0 has drastically changed the API. All available methods are on the docs page.

For legacy code, check out the 1.x branch and install it through npm install bowser@1.9.4.

Use cases

First of all, require the library. This is a UMD Module, so it will work for AMD, TypeScript, ES6, and CommonJS module systems.

const Bowser = require("bowser"); // CommonJS

import * as Bowser from "bowser"; // TypeScript

import Bowser from "bowser"; // ES6 (and TypeScript with --esModuleInterop enabled)

By default, the exported version is the ES5 transpiled version, which do not include any polyfills.

In case you don't use your own babel-polyfill you may need to have pre-built bundle with all needed polyfills. So, for you it's suitable to require bowser like this: require('bowser/bundled'). As the result, you get a ES5 version of bowser with babel-polyfill bundled together.

You may need to use the source files, so they will be available in the package as well.

Browser props detection

Often we need to pick users' browser properties such as the name, the version, the rendering engine and so on. Here is an example how to do it with Bowser:

const browser = Bowser.getParser(window.navigator.userAgent);

console.log(`The current browser name is "${browser.getBrowserName()}"`);
// The current browser name is "Internet Explorer"

Using User-Agent Client Hints

Modern browsers support User-Agent Client Hints, which provide a more privacy-friendly and structured way to access browser information. Bowser can use Client Hints data to improve browser detection accuracy.

// Pass Client Hints as the second parameter
const browser = Bowser.getParser(
  window.navigator.userAgent,
  window.navigator.userAgentData
);

console.log(`The current browser name is "${browser.getBrowserName()}"`);
// More accurate detection using Client Hints

Working with Client Hints

Bowser provides methods to access and query Client Hints data:

const browser = Bowser.getParser(
  window.navigator.userAgent,
  window.navigator.userAgentData
);

// Get the full Client Hints object
const hints = browser.getHints();
// Returns the ClientHints object or null if not provided

// Check if a specific brand exists
if (browser.hasBrand('Google Chrome')) {
  console.log('This is Chrome!');
}

// Get the version of a specific brand
const chromeVersion = browser.getBrandVersion('Google Chrome');
console.log(`Chrome version: ${chromeVersion}`);

The Client Hints object structure:

{
  brands: [
    { brand: 'Google Chrome', version: '131' },
    { brand: 'Chromium', version: '131' },
    { brand: 'Not_A Brand', version: '24' }
  ],
  mobile: false,
  platform: 'Windows',
  platformVersion: '15.0.0',
  architecture: 'x86',
  model: '',
  wow64: false
}

Note: Client Hints improve detection for browsers like DuckDuckGo and other Chromium-based browsers that may have similar User-Agent strings. When Client Hints are not provided, Bowser falls back to standard User-Agent string parsing.

or

const browser = Bowser.getParser(window.navigator.userAgent);
console.log(browser.getBrowser());

// outputs
{
  name: "Internet Explorer"
  version: "11.0"
}

or

console.log(Bowser.parse(window.navigator.userAgent));

// outputs
{
  browser: {
    name: "Internet Explorer"
    version: "11.0"
  },
  os: {
    name: "Windows"
    version: "NT 6.3"
    versionName: "8.1"
  },
  platform: {
    type: "desktop"
  },
  engine: {
    name: "Trident"
    version: "7.0"
  }
}

You can also use Bowser.parse() with Client Hints:

console.log(Bowser.parse(window.navigator.userAgent, window.navigator.userAgentData));

// Same output structure, but with enhanced detection from Client Hints

Filtering browsers

You could want to filter some particular browsers to provide any special support for them or make any workarounds. It could look like this:

const browser = Bowser.getParser(window.navigator.userAgent);
const isValidBrowser = browser.satisfies({
  // declare browsers per OS
  windows: {
    "internet explorer": ">10",
  },
  macos: {
    safari: ">10.1"
  },

  // per platform (mobile, desktop or tablet)
  mobile: {
    safari: '>=9',
    'android browser': '>3.10'
  },

  // or in general
  chrome: "~20.1.1432",
  firefox: ">31",
  opera: ">=22",

  // also supports equality operator
  chrome: "=20.1.1432", // will match particular build only

  // and loose-equality operator
  chrome: "~20",        // will match any 20.* sub-version
  chrome: "~20.1"       // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
});

Settings for any particular OS or platform has more priority and redefines settings of standalone browsers. Thus, you can define OS or platform specific rules and they will have more priority in the end.

More of API and possibilities you will find in the docs folder.

Browser names for .satisfies()

By default you are supposed to use the full browser name for .satisfies. But, there's a short way to define a browser using short aliases. The full list of aliases can be found in the file.

Similar Projects

  • Kong - A C# port of Bowser.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

License

Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.