bowser vs ua-parser-js vs platform
User Agent Parsing Libraries for JavaScript Applications
bowserua-parser-jsplatformSimilar Packages:

User Agent Parsing Libraries for JavaScript Applications

bowser, platform, and ua-parser-js are JavaScript utilities designed to parse User-Agent strings and environment data to identify browsers, operating systems, devices, and rendering engines. While they share the core goal of environment detection, they differ in API design, granularity of data, and broader platform support. bowser focuses on a modern, chainable API for browser specifics. platform provides a broad snapshot of the runtime environment, including Node.js and older browsers. ua-parser-js offers a highly detailed, synchronous parser that works across many JavaScript environments with a focus on accuracy and extensive device databases.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
bowser37,222,2545,737258 kB914 months agoMIT
ua-parser-js26,297,30010,1271.32 MB196 days agoAGPL-3.0-or-later
platform4,625,1693,246-346 years agoMIT

Bowser vs Platform vs UAParser: Deep Dive into UA Parsing

Parsing User-Agent strings is a common requirement for feature detection, analytics, and conditional rendering in web applications. While modern best practices often encourage feature detection over browser sniffing, there are still valid cases where knowing the client environment is necessary. bowser, platform, and ua-parser-js are the three most prominent tools for this task, but they approach the problem differently. Let's examine how they handle parsing, API design, and environment support.

๐Ÿ› ๏ธ API Design: Chainable vs Static vs Instance

The way you interact with these libraries varies significantly, impacting code readability and bundle integration.

bowser uses a functional, chainable API. You pass the User-Agent string to a parser instance and then call specific getters.

// bowser: Chainable parser
import bowser from 'bowser';

const parser = bowser.getParser(userAgent);
const browserName = parser.getBrowserName();
const isMobile = parser.isMobile();

platform exposes a static object that is populated immediately upon import. There is no need to instantiate a parser or pass a User-Agent string manually in browser contexts.

// platform: Static object
import platform from 'platform';

console.log(platform.name); // e.g., "Chrome"
console.log(platform.version); // e.g., "98.0.4758.102"
console.log(platform.os.family); // e.g., "Windows"

ua-parser-js relies on a class-based instance. You create a new parser, optionally passing a User-Agent string, and then retrieve a result object containing all data.

// ua-parser-js: Class instance
import UAParser from 'ua-parser-js';

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

console.log(result.browser.name); // e.g., "Chrome"
console.log(result.device.model); // e.g., "iPhone"

๐Ÿ” Detection Granularity: Browser vs Device vs Engine

Not all parsers dig equally deep. Some focus on the browser name, while others extract hardware and engine details.

bowser focuses primarily on the browser and OS. It excels at identifying browser families and versions but provides limited device hardware data.

// bowser: Browser and OS focus
const browser = parser.getBrowser();
// { name: 'Safari', version: '15.0' }

const os = parser.getOS();
// { name: 'macOS', version: '12.0' }

platform provides a balanced view of the environment, including layout engines and product names, but device model detection is less specific compared to dedicated parsers.

// platform: Environment snapshot
console.log(platform.layout); // e.g., "WebKit"
console.log(platform.product); // e.g., "Electron"
console.log(platform.description); // Full UA string description

ua-parser-js offers the most granular data, splitting results into browser, device, engine, CPU, and OS. It is particularly strong on mobile device models.

// ua-parser-js: Detailed breakdown
const device = result.device;
// { vendor: 'Apple', model: 'iPhone', type: 'mobile' }

const engine = result.engine;
// { name: 'WebKit', version: '605.1.15' }

๐ŸŒ Environment Support: Browser vs Node vs Workers

Where these libraries run matters, especially for isomorphic applications.

bowser is designed primarily for browsers but works in Node.js if you pass the User-Agent string manually. It does not auto-detect the environment in Node.

// bowser: Manual UA in Node
import bowser from 'bowser';
const parser = bowser.getParser(process.env.USER_AGENT || '');

platform is built to detect the environment automatically. It works seamlessly in browsers, Node.js, and even older JavaScript engines without configuration.

// platform: Auto-detection
// Works out of the box in Node or Browser
if (platform.name === 'Node.js') {
  // Handle server-side logic
}

ua-parser-js is universally compatible. It works in browsers, Node.js, and Web Workers. Like bowser, it requires manual UA string passing in non-browser environments.

// ua-parser-js: Universal compatibility
const parser = new UAParser(navigator.userAgent); // Browser
const serverParser = new UAParser(req.headers['user-agent']); // Node

โš ๏ธ Maintenance and Stability

Long-term support is critical for infrastructure libraries.

bowser is actively maintained with regular updates to handle new browser versions. It is lightweight and focuses on staying current with modern browser releases.

platform is stable but sees fewer updates. It is considered a mature library that prioritizes backward compatibility over cutting-edge device detection. It is often bundled with lodash.

ua-parser-js has a very high update frequency due to its reliance on community contributions for device patterns. It is the go-to choice when new devices must be recognized quickly.

๐Ÿ“Š Summary: Feature Comparison

Featurebowserplatformua-parser-js
API StyleChainable functionsStatic objectClass instance
Browser Dataโœ… Detailedโœ… Basicโœ… Very Detailed
Device ModelโŒ LimitedโŒ Limitedโœ… Extensive
Engine Infoโœ… Yesโœ… Yesโœ… Yes
Node.js Supportโœ… Manual UAโœ… Auto-detectโœ… Manual UA
Bundle Weight๐ŸŸข Lightweight๐ŸŸข Lightweight๐ŸŸก Moderate

๐Ÿ’ก Real-World Scenarios

Scenario 1: Conditional CSS Loading

You need to apply a specific class for Safari users due to a known rendering bug.

  • โœ… Best choice: bowser
  • Why? The API is readable and perfect for simple boolean checks.
// bowser: Simple check
if (parser.getBrowserName() === 'Safari') {
  document.body.classList.add('safari-fix');
}

Scenario 2: Analytics Dashboard

You want to track user devices, including specific phone models and operating systems.

  • โœ… Best choice: ua-parser-js
  • Why? You need the device model and vendor data that others lack.
// ua-parser-js: Analytics data
const { device, os } = parser.getResult();
analytics.track('page_view', {
  device: `${device.vendor} ${device.model}`,
  os: `${os.name} ${os.version}`
});

Scenario 3: Universal Library

You are writing a utility library that runs in Node.js, browsers, and legacy environments.

  • โœ… Best choice: platform
  • Why? It auto-detects the environment without extra configuration.
// platform: Environment check
if (platform.os.family === 'Windows') {
  // Handle Windows specific paths
}

๐Ÿ Final Recommendation

Selecting the right parser depends on what you need to know about the client.

  • Need simplicity and browser focus? Use bowser. It is clean, modern, and easy to read in conditional logic.
  • Need broad environment detection? Use platform. It is excellent for detecting Node.js vs Browser without extra setup.
  • Need deep device and engine details? Use ua-parser-js. It is the most powerful tool for analytics and precise device identification.

Final Thought: While these tools are useful, remember that User-Agent strings can be spoofed. For critical feature detection, always prefer checking for the actual API or capability (feature detection) whenever possible. Use these libraries for analytics, logging, or non-critical UI adjustments.

How to Choose: bowser vs ua-parser-js vs platform

  • bowser:

    Choose bowser if your primary need is clean, modern browser detection with a simple API. It is ideal for frontend applications where you need to quickly identify browser families (Chrome, Firefox, Safari) and versions without worrying about low-level engine details. Its chainable interface makes it easy to read and maintain in conditional logic.

  • ua-parser-js:

    Choose ua-parser-js if you require detailed parsing of device models, engine versions, and CPU architecture alongside browser data. It is the best fit for analytics, security fingerprinting, or complex feature detection where accuracy across a wide range of devices โ€” including mobile and smart TVs โ€” is critical.

  • platform:

    Choose platform if you need to detect the broader runtime environment, not just the browser. It is suitable for libraries that must run in diverse contexts like Node.js, Rhino, or legacy browsers, and when you need quick access to properties like platform.name or platform.os without instantiating a parser object.

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.