Skip to content

Advanced Usage

TypeScript types

All public types are exported from the package root:

ts
import type { OS } from 'os-detect'

// OS is a string union:
// 'ios' | 'macos' | 'android' | 'windows' | 'linux' | 'chromeos' | 'unknown'

Narrowing with getOS()

ts
import { getOS } from 'os-detect'
import type { OS } from 'os-detect'

const os: OS = getOS()

switch (os) {
  case 'ios':
  case 'android':
    console.log('Mobile device')
    break
  case 'windows':
  case 'macos':
  case 'linux':
  case 'chromeos':
    console.log('Desktop device')
    break
  case 'unknown':
    console.log('Unrecognised OS')
    break
}

TypeScript knows all branches are exhausted after the switch — no need for a default case if you handle 'unknown'.

React types

useOS() returns OS. useIsWindows11() returns boolean | null. Both are fully typed with no extra imports needed.

Vue types

useOS() returns Readonly<Ref<OS>>. useIsWindows11() returns Readonly<Ref<boolean | null>>.

ts
import type { OS } from 'os-detect'
import { useOS } from 'os-detect/vue'
import type { Ref } from 'vue'

const os: Readonly<Ref<OS>> = useOS()

Detection strategy

Browser

  1. navigator.userAgentData.platform (Chrome 90+ / Edge 90+) — the modern, high-entropy-free platform hint. Reliable and not spoofable by userAgent overrides.
  2. navigator.userAgent — legacy fallback for all other browsers (Firefox, Safari, older Chrome). Regex patterns are kept conservative to avoid false positives.

For Windows 11, an additional async call to navigator.userAgentData.getHighEntropyValues(['platformVersion']) is required — this is gated behind detectIsWindows11() and never called automatically.

Node.js

Reads process.platform when navigator is absent. No userAgent parsing is done server-side. detectIsWindows11() dynamically imports the built-in os module and parses the build number from os.release().

Caching

Results are stored in module-level variables after the first call. Subsequent calls return the cached value directly with no DOM or process access. This makes repeated calls in reactive contexts (render functions, computed properties) effectively free.

Limitations

Every detector ultimately relies on navigator.userAgentData or navigator.userAgent (or process.platform in Node.js). This has two structural consequences:

  • User agent strings can be spoofed by the browser, an extension, or devtools device emulation. There is no way to cryptographically verify the reported platform — treat results as a UX hint, not a security boundary.
  • navigator.userAgentData is a moving target. Chromium is progressively freezing/reducing the legacy navigator.userAgent string and gating more detail behind opt-in high-entropy values. Firefox and Safari don't implement userAgentData at all, so they always fall through to UA-string regexes. Future browser changes could require updated patterns — this is inherent to UA-based detection, not specific to this library.

Caching & resetDetectionCache

ts
import { resetDetectionCache } from 'os-detect'

resetDetectionCache() // clears every cached detection result

All detectIs*() functions and getOS() cache their result after the first call (see Caching above). In a normal browser tab the OS never changes mid-session, so this is never needed. It exists for advanced cases:

  • A long-running Node.js process (e.g. an Electron main process) that needs to re-evaluate process.platform after switching contexts.
  • Test suites that mock navigator/process.platform per test without re-importing the module.

detectIsWindows11() is not cached — it always re-runs its async check.