detect-browser

Detect browser vendor, version, and OS from a user-agent string

Library
npm
v5.3.0
699stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
42/100Fair
Development Activity0
Maintenance20
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture65
Code Quality70
Innovation72
Learning Curve80

detect-browser is a lightweight JavaScript and TypeScript library that parses a user-agent string — from the browser’s navigator.userAgent or Node’s process.version — into a structured result identifying the browser name, semver-compatible version, and operating system. It ships as a single dependency-free module with full TypeScript typings, covering major desktop and mobile browsers (Chrome, Firefox, Safari, Edge, Opera, and many more), search-bot user agents, React Native environments, and Node.js itself.

Rather than exposing raw regex matches, detect-browser returns typed result objects (BrowserInfo, NodeInfo, BotInfo, SearchBotDeviceInfo, ReactNativeInfo) discriminated by a type field, so consumers can branch on detection results safely in TypeScript. It has been a stable dependency since 2014 with over 2.5 million weekly npm downloads, making it a common building block for feature detection, analytics enrichment, and conditional polyfill loading.

What You Get

  • A single detect() function returning a typed result describing browser, Node, bot, bot-device, or React Native environments
  • Standalone browserName() and detectOS() helpers for narrower use cases
  • TypeScript declaration files and discriminated-union result types (BrowserInfo, NodeInfo, BotInfo, SearchBotDeviceInfo, ReactNativeInfo)
  • Coverage for dozens of browsers and OS families, including mobile browsers, in-app webviews, and known search-engine bots
  • Zero runtime dependencies plus both CommonJS and ES module builds

Common Use Cases

  • Feature-detecting unsupported browsers and showing an upgrade banner
  • Enriching analytics events with browser/OS metadata without a heavier UA-parsing library
  • Branching server-side rendering or polyfill loading based on the requesting client
  • Filtering search-engine bot traffic out of session or analytics tracking

Under The Hood

Architecture detect-browser is a single ~300-line src/index.ts module. The detect() entry point dispatches on the runtime environment — an explicit user agent string, a React Native navigator.product check, a browser navigator.userAgent read, or a Node.js fallback via process.version — and delegates string parsing to parseUserAgent(). That function walks an ordered array of [Browser, RegExp] tuples (userAgentRules) with Array.reduce, returning on the first match, then runs a parallel ordered scan of operatingSystemRules in detectOS(). Results are wrapped in small discriminated-union classes (BrowserInfo, NodeInfo, BotInfo, SearchBotDeviceInfo, ReactNativeInfo) that all implement a shared DetectedInfo<T, N, O, V> interface with a readonly type field, so TypeScript consumers can narrow the result with a switch. The whole library is a pure function over a string input with no state, no I/O, and no side effects.

Tech Stack The package has zero runtime dependencies. package.json declares dual build outputs — main for CommonJS (index.js, compiled by tsc) and module for ES modules (es/index.js, compiled with tsc --outDir es --module es6 --declaration false) — plus bundled .d.ts types, none of which are committed to the repo (they’re generated at publish time via the compile/prepare npm scripts). Dev tooling is TypeScript 4.4, tape for tests, tslint for linting, prettier for formatting, npm-run-all to chain the build/test/lint pipeline, rimraf to clean the es/ output directory, and semver used only in tests to assert detected versions are valid semver strings.

Code Quality test/logic.js is a 550+ line table-driven suite asserting parseUserAgent() output against dozens of real, hand-picked user-agent strings per browser (Chrome, Chrome for iOS, Firefox, Firefox for iOS, and many more), giving strong regression coverage against a large corpus of real-world UA strings. test/highLevel.js sanity-checks detect() end-to-end and its semver compatibility, and both run via tape through a two-line test/index.js entry point (no coverage or watch tooling configured). The source itself has no duplication, consistent naming (camelCase functions, PascalCase classes), and explicit TypeScript interfaces/discriminated unions; it has little inline documentation beyond a few comments explaining non-obvious regex ordering decisions.

API Design A single detect() call covers the common case with zero configuration and returns a typed result consumers can switch on by name or type. browserName() and detectOS() are exposed separately for callers who only need one piece of information, avoiding forcing every caller through the full object. The type discriminator makes the API pleasant to use from TypeScript (exhaustive switch statements), and the README documents both an if/switch idiom and a discriminator-based example, keeping the learning curve to a single import and one function call. The main friction point is that adding support for a new browser or newer UA string requires a PR to the library itself — there’s no user-supplied rule extension point — and the last feature release was in 2021.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search