Skip to content

API Reference

uaBrowser()

Detect the current browser environment and return a full environment info object. Automatically reads navigator.userAgent and injects the navigator context (language, platform, touch points).

typescript
import uaBrowser from 'ua-browser'

uaBrowser(): EnvOption

Returns: EnvOption

Example:

typescript
const info = uaBrowser()
console.log(info.browser) // 'Chrome'
console.log(info.os)      // 'Windows'

Notes:

  • Returns 'unknown' for fields that cannot be determined, never an empty string.
  • In Node.js, navigator is unavailable; language and platform will be 'unknown'.
  • To parse an arbitrary UA string, use parseUA().
  • For higher accuracy in browsers, use uaBrowser.detect().

The default export also exposes the following static members:

typescript
uaBrowser.detect(): Promise<EnvOption>
uaBrowser.isWebview(ua: string): boolean
uaBrowser.getLanguage(): string
uaBrowser.VERSION: string

uaBrowser.detect()

Async, high-accuracy version of uaBrowser(). Internally calls getEnvContext() to collect hardware and browser signals before parsing, enabling more accurate device type and CPU architecture detection.

This is the recommended entry point for browser-side code.

typescript
uaBrowser.detect(): Promise<EnvOption>

Returns: Promise<EnvOption>

Signals collected by detect():

SignalPurpose
Client Hints (Sec-CH-UA-*)Exact version, platform, architecture
WebGL renderer / vendorGPU type → mobile vs. desktop, Apple Silicon vs. Intel
CSS env(safe-area-inset-top)iOS notch / Dynamic Island → confirms mobile device
devicePixelRatioPhone (≥3) vs. Mac (2) vs. monitor (1–2)
Vibration / DeviceMotion APIsMobile-only APIs → confirms mobile intent
Network type (connection.effectiveType)Supplements device classification
Font probesOS-level font availability

Example:

typescript
import uaBrowser from 'ua-browser'

const result = await uaBrowser.detect()
console.log(result.device) // 'Mobile' — correct even in desktop mode
console.log(result.arch)   // 'arm64' or 'x86_64'

Notes:

  • Browser-only. In Node.js getEnvContext() returns empty context, so the result is equivalent to uaBrowser().
  • All DOM accesses are wrapped in try/catch and will not throw.

parseUA(ua, options?)

Pure function: no global state, no DOM access. Suitable for SSR, Node.js, and unit testing.

typescript
import { parseUA } from 'ua-browser'

parseUA(ua: string, options?: ParseOptions): EnvOption
ParameterTypeRequiredDescription
uastringYesUA string to parse.
optionsParseOptionsNoInject context; see below.

ParseOptions fields:

FieldTypeDescription
navNavContextBrowser environment subset (language, platform, touch points). Use getNavContext() to read from navigator.
windowsVersionstring | nullPre-resolved Windows version string from getWindowsVersion(). Needed to distinguish Windows 10 vs. 11.
ctxEnvContextFull multi-signal context from getEnvContext(). Takes priority over nav and windowsVersion when both are provided.
customBotDefsreadonly BotDef[]Custom bot detection rules inserted before the GenericBot catch-all. Does not affect global state.
languagestringExplicit language override (BCP47). Highest priority — overrides all navigator/header sources. Useful for server-side rendering when passing Accept-Language.

Returns: EnvOption

Examples:

typescript
// Minimal: UA string only
const result = parseUA(navigator.userAgent)

// With navigator context (language/platform populated)
import { parseUA, getNavContext } from 'ua-browser'
const nav = getNavContext()
const result = parseUA(navigator.userAgent, { nav })
console.log(result.language) // 'en-US'
console.log(result.platform) // 'Win32'

// With full env context (multi-signal detection enabled)
import { parseUA, getEnvContext } from 'ua-browser'
const ctx = await getEnvContext()
const result = parseUA(navigator.userAgent, { ctx })
console.log(result.arch) // 'arm64' (from WebGL / Client Hints)

// With custom bot rules
import { parseUA } from 'ua-browser'
import type { BotDef } from 'ua-browser'
const myBots: BotDef[] = [{ name: 'GenericBot', detect: /MyInternalCrawler/ }]
const result = parseUA(ua, { customBotDefs: myBots })

parseHeaders(headers)

Parse UA and Client Hints from HTTP request headers. Returns EnvOption. Suitable for precise SSR detection.

typescript
import { parseHeaders, ACCEPT_CH } from 'ua-browser'

parseHeaders(headers: Record<string, string | string[] | undefined>): EnvOption
ParameterTypeRequiredDescription
headersRecord<string, string | string[] | undefined>YesHTTP request headers object (e.g. req.headers in Express / Next.js).

Returns: EnvOption

Client Hints headers read:

HeaderData
user-agentFull UA string
sec-ch-uaBrowser brand list
sec-ch-ua-full-version-listExact browser version
sec-ch-ua-platformOS name
sec-ch-ua-platform-versionOS version (distinguishes Windows 10 / 11)
sec-ch-ua-archCPU architecture (e.g. x86, arm)
sec-ch-ua-mobileMobile hint

Two-request pattern:

On the first request, browsers only send the user-agent header. Return ACCEPT_CH in the response to request Client Hints; they arrive on subsequent requests.

typescript
import { parseHeaders, ACCEPT_CH } from 'ua-browser'

// First response — tell the browser to send Client Hints
res.setHeader('Accept-CH', ACCEPT_CH)

// Subsequent requests — full Client Hints included
const result = parseHeaders(req.headers)
console.log(result.arch) // 'x86_64' (from Sec-CH-UA-Arch)
console.log(result.os)   // 'Windows'

Notes:

  • Works with Express, Koa, Next.js API routes, Fastify, Hono, etc. — any framework that exposes headers as a plain object.
  • If Client Hints headers are absent, falls back to UA-only parsing.

getEnvContext()

Collect all available browser signals in one async call and return an EnvContext object. Pass the result to parseUA({ ctx }) for multi-signal detection.

typescript
import { getEnvContext } from 'ua-browser'

getEnvContext(): Promise<EnvContext>

Returns: Promise<EnvContext>

Signals collected:

CategorySignals
Client Hintsplatform, platformVersion, architecture, fullVersionList
WebGLGPU renderer + vendor, max texture size, compressed texture formats (ASTC/ETC2/PVRTC/S3TC)
ScreendevicePixelRatio, screenWidth, screenHeight
CSS envsafe-area-inset-top (iOS notch / Dynamic Island)
Hardware APIshardwareConcurrency, deviceMemory, vibration API, DeviceMotion event
InputpointerType (coarse/fine/none), hover capability
Networkconnection.effectiveType, connection.saveData
AudioSample rate
FontsOS-specific font availability probes

Example:

typescript
import { getEnvContext, parseUA } from 'ua-browser'

const ctx = await getEnvContext()
const result = parseUA(navigator.userAgent, { ctx })

console.log(result.device)   // 'Mobile' — correct even in desktop mode
console.log(result.arch)     // 'arm64' (Apple Silicon) or 'x86_64' (Intel)
console.log(result.language) // 'en-US'

Notes:

  • Browser-only. Safe to call in Node.js — all DOM accesses are guarded and return undefined; the result is equivalent to getNavContext().
  • Each DOM API is wrapped in an individual try/catch, so a single permission denial does not block the rest.
  • Prefer uaBrowser.detect() if you don't need to reuse the ctx object.

getWindowsVersion(nav)

Asynchronously resolve the accurate Windows version to distinguish Windows 10 from Windows 11 (which share the same UA string: Windows NT 10.0).

typescript
import { getWindowsVersion, getNavContext, parseUA } from 'ua-browser'

getWindowsVersion(nav: NavContext): Promise<string | null>
ParameterTypeRequiredDescription
navNavContextYesBrowser context; pass getNavContext().

Returns: Promise<string | null> — the version string (e.g. '11', '10') or null when unavailable.

Example:

typescript
const nav = getNavContext()
const windowsVersion = await getWindowsVersion(nav)
const result = parseUA(navigator.userAgent, { nav, windowsVersion })

console.log(result.osVersion) // '11' or '10'

Notes:

  • Requires navigator.userAgentData.getHighEntropyValues() (Chrome 90+, Edge 90+).
  • Returns null in Firefox, Safari, and Node.js — osVersion falls back to UA-derived value.
  • getEnvContext() already calls this internally; use getWindowsVersion() directly only when you want NavContext-level context without the full EnvContext overhead.

detectBot(ua, customDefs?)

Standalone bot detector. Returns the bot detection result without running the full parseUA() pipeline.

typescript
import { detectBot } from 'ua-browser'
import type { BotDef } from 'ua-browser'

detectBot(ua: string, customDefs?: readonly BotDef[]): { isBot: boolean; botName: BotName; botCategory: BotCategory }
ParameterTypeRequiredDescription
uastringYesUA string to test.
customDefsreadonly BotDef[]NoAdditional bot rules. Inserted after built-in rules, before GenericBot catch-all.

Returns: { isBot: boolean; botName: BotName; botCategory: BotCategory }

BotDef shape:

typescript
interface BotDef {
  name: BotName         // the bot label returned in botName
  detect: RegExp        // matched against the UA string
  category: BotCategory // bot classification
}

Example:

typescript
const { isBot, botName, botCategory } = detectBot(ua)
// isBot: true, botName: 'Googlebot', botCategory: 'search-engine'

// Custom rules
const myDefs: BotDef[] = [
  { name: 'GenericBot', detect: /MyInternalCrawler/ }
]
detectBot(ua, myDefs)

// Or pass through parseUA for a full result
parseUA(ua, { customBotDefs: myDefs })

Notes:

  • Built-in rules cover 30+ bots including AI training crawlers (GPTBot, ClaudeBot, PerplexityBot, CCBot, etc.).
  • customDefs do not modify any global state.

detectArch(ua, ctx?)

Standalone CPU architecture detector. Without ctx, falls back to UA-string heuristics only.

typescript
import { detectArch } from 'ua-browser'

detectArch(ua: string, ctx?: EnvContext): ArchName
ParameterTypeRequiredDescription
uastringYesUA string.
ctxEnvContextNoMulti-signal context from getEnvContext(). Enables GPU and Client Hints detection.

Returns: ArchName'x86' | 'x86_64' | 'arm' | 'arm64' | 'unknown'

Detection priority chain:

  1. Client Hints Sec-CH-UA-Arch (highest accuracy)
  2. WebGL renderer string (ANGLE → x86/x86_64; Apple GPU → arm64; Adreno/Mali → arm64)
  3. navigator.platform (e.g. 'Win32' → x86_64; 'iPhone' → arm64)
  4. UA string patterns (lowest accuracy — affected by UA freezing)

Example:

typescript
import { detectArch, getEnvContext } from 'ua-browser'

const ctx = await getEnvContext()
const arch = detectArch(navigator.userAgent, ctx)
// 'arm64' on Apple Silicon, 'x86_64' on Intel Mac

detectHeadless(ua)

Detect whether the UA string indicates a headless browser.

typescript
import { detectHeadless } from 'ua-browser'

detectHeadless(ua: string): boolean
ParameterTypeRequiredDescription
uastringYesUA string to test.

Returns: boolean

Detected markers: HeadlessChrome, Headless, PhantomJS, Electron, Playwright, jsdom, Selenium and other common headless identifiers.

Note: Tools that spoof a real UA (e.g. Puppeteer with a custom UA) cannot be detected by string matching alone.

Example:

typescript
detectHeadless('Mozilla/5.0 ... HeadlessChrome/124.0.0.0 ...')
// true

isWebview(ua)

Detect whether the UA indicates an embedded WebView (Android Webview or iOS WKWebView).

typescript
import { isWebview } from 'ua-browser'

isWebview(ua: string): boolean
ParameterTypeRequiredDescription
uastringYesUA string to test.

Returns: boolean

Detection logic:

  • Android Webview: UA contains ; wv) marker
  • iOS WKWebView: Safari UA that lacks both Version/ token and Safari/ token (WKWebView strips them)

Example:

typescript
isWebview('Mozilla/5.0 (Linux; Android 10; K; wv) ...') // true  (Android)
isWebview('Mozilla/5.0 (iPhone ...) ... Mobile/15E148')  // true  (iOS WKWebView)
isWebview('Mozilla/5.0 ... Version/17.4 ... Safari/604.1') // false (real Safari)

getNavContext()

Read the current browser's navigator and return a NavContext object. In Node.js, returns a safe empty object so callers do not need environment checks.

typescript
import { getNavContext } from 'ua-browser'

getNavContext(): NavContext

Returns: NavContext

Example:

typescript
const nav = getNavContext()
const result = parseUA(navigator.userAgent, { nav })

console.log(result.language) // 'en-US'
console.log(result.platform) // 'Win32'

Notes:

  • Prefer getEnvContext() when you also need arch / device accuracy signals.
  • getNavContext() is synchronous; getEnvContext() is async.

getLanguage(nav)

Extract the normalized browser language from a NavContext. Normalizes the tag to standard BCP 47 form (e.g. 'en-us''en-US', 'ZH_CN''zh-CN').

typescript
import { getLanguage, getNavContext } from 'ua-browser'

getLanguage(nav: NavContext): string
ParameterTypeRequiredDescription
navNavContextYesBrowser context.

Returns: string — normalized language tag, e.g. 'en-US', 'zh-CN', or 'unknown'.

Example:

typescript
const nav = getNavContext()
console.log(getLanguage(nav)) // 'en-US'

ACCEPT_CH

Constant string containing all Client Hints headers that parseHeaders() can consume. Set it as the Accept-CH response header to request these hints from supporting browsers (Chrome / Edge 90+).

typescript
import { ACCEPT_CH } from 'ua-browser'

ACCEPT_CH: string
// 'Sec-CH-UA, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch, Sec-CH-UA-Mobile'

Example:

typescript
res.setHeader('Accept-CH', ACCEPT_CH)
res.setHeader('Vary', 'Sec-CH-UA, Sec-CH-UA-Full-Version-List')  // optional but recommended

detectBrowser(ua)

Standalone browser detector that does not run the full parseUA() pipeline.

typescript
import { detectBrowser } from 'ua-browser'

detectBrowser(ua: string): { browser: BrowserName; version: string; browserType: BrowserType }
ParameterTypeRequiredDescription
uastringYesUA string

Returns: { browser: BrowserName; version: string; browserType: BrowserType }

Example:

typescript
const { browser, version, browserType } = detectBrowser(navigator.userAgent)
// browser: 'Chrome', version: '124.0.0.0', browserType: 'browser'

detectOS(ua)

Standalone OS detector that does not run the full parseUA() pipeline.

typescript
import { detectOS } from 'ua-browser'

detectOS(ua: string): { os: OsName; osVersion: string; osVersionName: string }
ParameterTypeRequiredDescription
uastringYesUA string

Returns: { os: OsName; osVersion: string; osVersionName: string }

Example:

typescript
const { os, osVersion, osVersionName } = detectOS(navigator.userAgent)
// os: 'Windows', osVersion: '10', osVersionName: 'Windows 10'

detectEngine(ua)

Standalone rendering engine detector. Does not run the full parseUA() pipeline.

typescript
import { detectEngine } from 'ua-browser'

detectEngine(ua: string): { engine: EngineName; engineVersion: string }
ParameterTypeRequiredDescription
uastringYesUser agent string

Returns: { engine: EngineName; engineVersion: string }

Example:

typescript
const { engine, engineVersion } = detectEngine(navigator.userAgent)
// engine: 'Blink', engineVersion: '537.36'

detectVendorModel(ua)

Standalone device vendor/model extractor.

typescript
import { detectVendorModel } from 'ua-browser'

detectVendorModel(ua: string): VendorModelResult
ParameterTypeRequiredDescription
uastringYesUser agent string

Returns: VendorModelResult

Example:

typescript
const { vendor, model } = detectVendorModel(ua)
// vendor: 'Samsung', model: 'SM-G991B'

detectDevice(ua)

Standalone device type detector. Does not run the full parseUA() pipeline. UA-only — does not use hardware signals.

typescript
import { detectDevice } from 'ua-browser'

detectDevice(ua: string): DeviceName
ParameterTypeRequiredDescription
uastringYesUser agent string

Returns: DeviceName

Example:

typescript
const device = detectDevice(navigator.userAgent)
// device: 'Mobile'

satisfies(info, criteria)

Condition-matching helper. TypeScript-aware, cleaner than chaining && expressions.

typescript
import { satisfies } from 'ua-browser'

satisfies(info: EnvOption, criteria: Partial<EnvOption>): boolean
ParameterTypeRequiredDescription
infoEnvOptionYesReturn value from parseUA() or uaBrowser()
criteriaPartial<EnvOption>YesSubset of fields to match against

Returns: boolean

Example:

typescript
import uaBrowser, { satisfies } from 'ua-browser'

const info = uaBrowser()

// equivalent to: info.os === 'iOS' && info.device === 'Mobile'
if (satisfies(info, { os: 'iOS', device: 'Mobile' })) {
  // ...
}

// match AI crawlers only
if (satisfies(info, { isBot: true, botCategory: 'ai-llm' })) {
  // ...
}

// match in-app browsers (WeChat, DingTalk, etc.)
if (satisfies(info, { browserType: 'app' })) {
  // ...
}

VERSION

The current library version string, matching version in package.json.

typescript
import { VERSION } from 'ua-browser'

VERSION: string  // e.g. '2.0.0'

Released under the MIT License.