Reader Stacks

How to Check the User's Browser or Device in Angular

navigator.userAgent is plain browser JavaScript, not an Angular API — genuinely useful for a quick check, but it's a notoriously unreliable string to parse for anything beyond the broadest categories.

How to Check the User's Browser or Device in Angular

Detecting a visitor's browser or device type in Angular relies on the same plain browser JavaScript navigator.userAgent string every other framework uses — Angular adds no special API here, just a wrapper worth building for testability and SSR-safety.

Reading the raw user agent string

console.log(navigator.userAgent);
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."

A basic mobile-vs-desktop check

isMobileDevice(): boolean {
    return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
}

Wrapping it in an injectable service

@Injectable({ providedIn: 'root' })
export class DeviceDetectionService {
    isMobile(): boolean {
        return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
    }

    isSafari(): boolean {
        return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    }

    isIOS(): boolean {
        return /iPad|iPhone|iPod/.test(navigator.userAgent);
    }
}

Wrapping these checks in a service, rather than calling navigator.userAgent directly from components, keeps device detection mockable in unit tests and gives one place to update the detection logic if it ever needs refinement.

Handling server-side rendering safely

import { isPlatformBrowser } from '@angular/common';
import { PLATFORM_ID, Inject } from '@angular/core';

constructor(@Inject(PLATFORM_ID) private platformId: Object) {}

isMobile(): boolean {
    if (!isPlatformBrowser(this.platformId)) {
        return false;
    }
    return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
}

navigator doesn't exist during Angular Universal's server-side rendering pass — checking isPlatformBrowser() first prevents a genuine runtime error when this code runs during SSR, the same platform-check pattern needed for localStorage access covered elsewhere on this site.

Why user agent parsing is notoriously unreliable

Browsers have a long history of adding other browsers' names into their own user agent string for compatibility reasons (Chrome's string contains "Safari", Edge's contains "Chrome") — this is exactly why naive substring checks (like the Safari regex above, which has to explicitly exclude "chrome") are fragile and can misidentify a browser; a dedicated, actively maintained parsing library is more reliable than hand-rolled regex for anything beyond the broadest mobile/desktop distinction.

Using a dedicated library for more reliable detection

npm install ua-parser-js
import { UAParser } from 'ua-parser-js';

const parser = new UAParser();
const result = parser.getResult();

console.log(result.browser.name); // "Chrome"
console.log(result.os.name);      // "Windows"
console.log(result.device.type);  // "mobile" | "tablet" | undefined (desktop)

Feature detection as a more robust alternative

const supportsTouchEvents = 'ontouchstart' in window;

For many real use cases (like deciding whether to show touch-friendly UI), checking whether a specific browser feature is actually supported (feature detection) is more robust than inferring it from the device type via user agent — a laptop with a touchscreen, for instance, would be misclassified as "desktop, no touch" by user agent alone, while feature detection correctly identifies its actual touch capability.