---
title: "Browser"
description: "Cheap user-agent / platform / capability detector. Useful for runtime branches in front-end code."
canonical_url: "https://bitrix24.github.io/b24jssdk/docs/working-with-the-rest-api/tools-browser"
last_updated: "2026-07-01"
---
# Browser

> Cheap user-agent / platform / capability detector. Useful for runtime branches in front-end code.

## Overview

`Browser`{className="language-ts-type shiki shiki-themes material-theme-lighter material-theme material-theme-palenight" language="ts-type" style=""} is a singleton (`new BrowserManager()`) exported from `@bitrix24/b24jssdk`. It bundles cheap user-agent / platform / capability checks the SDK relies on internally and exposes them for application code:

- **Browser detection** — Opera, Internet Explorer (6 through 11, plus a numeric `detectIEVersion`), Safari, Firefox, Chrome.
- **OS / platform detection** — macOS, Windows, Linux, Android (with `detectAndroidVersion`), iPad, iPhone, and a combined `isIOS`.
- **Capabilities** — `isMobile`, `isRetina`, `isTouchDevice`, `isDoctype`, and `isLocalStorageSupported`.

All checks are derived from a module-level `UA` string — a lower-cased `navigator.userAgent` captured once at import time — or from browser globals (`window`, `document`, `navigator`, `localStorage`). Because of this, `Browser` is only meaningful in a browser context.

```ts
import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isMobile()) {
  // ...
}

if (Browser.isLocalStorageSupported()) {
  // ...
}
```

## Method Signature

### Browser detection

```ts-type
isOpera(): boolean                           // UA includes 'opera'
isIE(): boolean                              // legacy 'attachEvent' in document, and not Opera
isIE6(): boolean                             // UA includes 'msie 6'
isIE7(): boolean                             // UA includes 'msie 7'
isIE8(): boolean                             // UA includes 'msie 8'
isIE9(): boolean                             // document.documentMode >= 9
isIE10(): boolean                            // document.documentMode >= 10
isIE11(): boolean                            // detectIEVersion() >= 11
detectIEVersion(): number                    // numeric IE version, -1 if not IE
isSafari(): boolean                          // UA includes 'safari' and not 'chrome'
isFirefox(): boolean                         // UA includes 'firefox'
isChrome(): boolean                          // UA includes 'chrome'
```

### OS / platform detection

```ts-type
isMac(): boolean                             // UA includes 'macintosh'
isWin(): boolean                             // UA includes 'windows'
isLinux(): boolean                           // UA includes 'linux', and not Android
isAndroid(): boolean                         // UA includes 'android'
detectAndroidVersion(): number               // parsed Android version, 0 if not detected
isIPad(): boolean                            // UA includes 'ipad;', or Mac + touch
isIPhone(): boolean                          // UA includes 'iphone;'
isIOS(): boolean                             // isIPad() || isIPhone()
```

### Capabilities

```ts-type
isMobile(): boolean                          // iPhone / iPad / Android / 'mobile' / 'touch' UA
isRetina(): boolean                          // window.devicePixelRatio >= 2
isTouchDevice(): boolean                     // 'ontouchstart' in window, or maxTouchPoints > 0
isDoctype(target?: any): boolean             // compatMode === 'CSS1Compat' (or fallback)
isLocalStorageSupported(): boolean           // setItem/removeItem round-trip succeeds
```

## Key Concepts

> [!NOTE]
> `Browser` reads `navigator.userAgent` into a module-level `UA` variable **once**, at import time. It is wrapped in a `try`/`catch`, so importing the module in a non-browser environment (e.g. Node/SSR) does not throw — `UA` simply falls back to `'?'` and every UA-based check returns `false`. Methods that touch `window`, `document`, or `localStorage` directly (`isRetina`, `isTouchDevice`, `isDoctype`, `isLocalStorageSupported`, `isIE`/`isIE9`/`isIE10`) still assume those globals exist, so calling them outside a browser can throw.

> [!CAUTION]
> This is user-agent sniffing, not feature detection. User agent strings can be spoofed or empty, and browsers increasingly freeze/reduce UA details. Prefer feature detection (e.g. checking for the API you actually need) where possible, and treat `Browser` as a best-effort heuristic for cosmetic/UX branching rather than a security or correctness boundary.

- **`isIPad()` covers modern iPadOS.** Since iPadOS reports itself as macOS in the UA string, `isIPad()` also returns `true` for a Mac-flavoured UA that also reports touch support (`isTouchDevice()`), which is how it distinguishes an iPad from a real desktop Mac.
- **`detectIEVersion()` returns `-1` for non-IE browsers.** It short-circuits to `-1` for Opera, Safari, Firefox, and Chrome before running the IE/Trident-specific heuristics, so it is safe to call unconditionally.
- **`isDoctype(target?)` accepts any document-like object.** Pass an iframe's `document` (or similar) to check *its* rendering mode instead of the top-level page; omitting `target` falls back to the global `document`.
- **`isLocalStorageSupported()` is a real write/remove probe**, not just a `typeof localStorage` check — it also catches cases where the API exists but throws (private browsing modes, storage quota exhausted, disabled by policy).

## Error Handling

`Browser` is designed for browser runtimes. The module-level user-agent read and `isLocalStorageSupported()` are wrapped in `try/catch`, but most checks dereference `document` / `window` / `navigator` directly (for example `isIE`, `isIE9`, `isRetina`, `isTouchDevice`, `detectIEVersion`, `detectAndroidVersion`) and throw a `ReferenceError` when those globals are absent. Guard any call behind an environment check (or avoid `Browser` entirely) in Node.js / SSR code paths that may execute before hydration.

## Examples

Browser detection:

```ts
import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isChrome()) {
  // Chrome-specific behaviour
}

if (Browser.isIE()) {
  const version = Browser.detectIEVersion()
  console.log(`Running on Internet Explorer ${version}`)
}
```

OS / platform branching:

```ts
import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isIOS()) {
  // Shared iPhone / iPad branch
}

if (Browser.isAndroid()) {
  const version = Browser.detectAndroidVersion()
  console.log(`Android version: ${version}`)
}
```

Capability checks:

```ts
import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isMobile() && Browser.isTouchDevice()) {
  // Adjust layout / hit-targets for touch
}

if (Browser.isRetina()) {
  // Serve high-resolution assets
}
```

Guarding `localStorage` access and checking a document's rendering mode:

```ts
import { Browser } from '@bitrix24/b24jssdk'

function persist(key: string, value: string): void {
  if (!Browser.isLocalStorageSupported()) {
    return
  }

  localStorage.setItem(key, value)
}

if (!Browser.isDoctype(document)) {
  console.warn('Page is rendered in quirks mode')
}
```

## Alternatives and Recommendations

- **Prefer feature detection over UA sniffing when possible.** `Browser`'s checks are heuristics based on `navigator.userAgent`, which can be spoofed, frozen, or reduced by the browser. For example, prefer checking `'ontouchstart' in window` directly (or `Browser.isTouchDevice()`, which does exactly that) over inferring touch support from platform checks.
- **Use `isMobile()` / `isTouchDevice()` for layout decisions, not for gating functionality.** Treat them as UX hints (e.g. bigger tap targets, simplified navigation) rather than as a way to disable features outright — a desktop browser in a touch-enabled laptop is a legitimate combination.
- **The IE-related methods (`isIE*`, `detectIEVersion`, `isIE11`) target long-retired browsers.** Keep them only for legacy compatibility branches; new code targeting current browsers generally does not need them.
- **Runtime type checks for values (not the environment) live in [`Type`](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/tools-type.md).** `Browser` answers "what am I running in", while `Type` answers "what shape is this value".

## Sitemap

See the full [sitemap](/b24jssdk/sitemap.md) for all pages.
