detect-browser
Detect browser vendor, version, and OS from a user-agent string
Repository Health
Technical Analysis
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()anddetectOS()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.
Used by 4 apps in this directory
Gotify
Monitoring · Developer Tools
A lightweight, self-hosted push notification server that sends and receives messages in real time over WebSocket, with a sleek web UI and a native Go plugin system.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Tianji
Analytics · Monitoring
Replace Google Analytics, UptimeKuma, and Prometheus with one self-hosted platform that tracks websites, monitors uptime, and reports server health.
Umami
Analytics
Privacy-first web analytics that respects your users — self-hosted, cookieless, and GDPR compliant out of the box.