Developer Guide

How to Detect Browser with JavaScript

A comprehensive, up-to-date guide covering feature detection, User-Agent Client Hints, classic UA parsing, and best practices for 2026.

What is the most reliable way to detect a browser in JavaScript?

Feature detection is the most reliable approach. Instead of checking the user agent string (which can be spoofed), test for the existence of specific APIs or CSS properties. For example, check for 'chrome' in window for Chrome, or test CSS support with CSS.supports(). Libraries like Bowser or UAParser.js provide reliable parsing as a fallback.

Method 1: Feature Detection (Recommended)

Feature detection is the gold standard for browser detection. Instead of asking "which browser is this?", you ask "does this browser support what I need?" This approach is more resilient to browser updates, spoofing, and the ongoing deprecation of user agent strings.

The principle is simple: test for the existence of APIs, properties, or behaviors rather than browser names. If a feature exists, use it; if not, provide a fallback. This naturally handles new browsers and updated versions without code changes.

Method 2: User-Agent Client Hints (Modern API)

User-Agent Client Hints is the modern replacement for the classic navigator.userAgent string. It provides structured, reliable data about the browser and platform. Available in Chromium-based browsers (Chrome 90+, Edge 90+, Opera 76+), but not yet in Firefox or Safari.

Method 3: User Agent String Parsing (Legacy)

While being phased out, navigator.userAgent still works in all browsers and remains necessary when Client Hints aren't available (Firefox, Safari). Use it as a fallback, and always combine with feature detection for critical functionality.

Browser Detection in React

In React applications, wrap browser detection in a custom hook to ensure it runs client-side and memoizes results. Here's a production-ready implementation:

Best Practices for Browser Detection

Prefer feature detection over browser detection. Instead of checking "is this Chrome?", check "does this browser support the Intersection Observer API?" This is more reliable and future-proof.

Use Client Hints when available. Fall back to UA parsing only when navigator.userAgentData is undefined (Firefox, Safari).

Never block users based on browser detection. Show warnings or suggest alternatives, but always allow access. Browser detection can be wrong.

Cache detection results. Browser info doesn't change during a session. Compute once and reuse.

Handle SSR gracefully. In Next.js or Remix, navigator doesn't exist on the server. Always check typeof window !== 'undefined' first.

Use established libraries for production. Bowser, UAParser.js, and Platform.js handle thousands of edge cases. Don't reinvent the wheel for critical detection logic.

Test with real devices. Emulators and DevTools device modes don't perfectly replicate real browser behavior. Use BrowserStack, Sauce Labs, or real hardware for verification.

Frequently Asked Questions

What is the most reliable way to detect a browser in JavaScript?

Feature detection is the most reliable approach. Instead of checking the user agent string (which can be spoofed), test for the existence of specific APIs or CSS properties. For example, check for 'chrome' in window for Chrome, or test CSS support with CSS.supports(). Libraries like Bowser or UAParser.js provide reliable parsing as a fallback.

Why is user agent string detection unreliable?

User agent strings are unreliable because: browsers often include other browser names for compatibility (Chrome includes 'Safari'), users can spoof their UA string, and Google is gradually freezing the Chrome UA string through User-Agent Client Hints. Many UA strings contain misleading information for historical compatibility reasons.

What is navigator.userAgentData and how do I use it?

navigator.userAgentData is the modern replacement for navigator.userAgent, part of the User-Agent Client Hints API. It provides structured data (brands, mobile flag, platform) instead of an unparsable string. Use navigator.userAgentData.brands to get browser name and version. It's available in Chrome 90+ and Edge 90+ but not yet in Firefox or Safari.

Should I use a library for browser detection?

For production applications, yes. Libraries like Bowser (8KB gzipped) and UAParser.js (17KB) handle edge cases, regular updates for new browsers, and cross-platform detection. For simple checks (like showing a 'best in Chrome' banner), a lightweight feature detection approach is sufficient.

How do I detect browser version in JavaScript?

Using User-Agent Client Hints: navigator.userAgentData.brands returns an array of {brand, version} objects. Using the classic approach: parse navigator.userAgent with a regex like /Chrome\\/(\\d+)/ for Chrome. Libraries like UAParser.js provide parsed version objects. Always handle cases where detection fails gracefully.

Can I detect if a browser is running in incognito/private mode?

Reliably detecting incognito mode has become increasingly difficult as browsers close detection methods. Historically, you could test storage quotas or the FileSystem API. Modern browsers (Chrome 76+, Firefox 77+) have patched these methods. Attempting to detect private mode is generally considered a privacy violation.

How do I detect a mobile browser vs desktop browser?

The most reliable method combines multiple signals: navigator.userAgentData?.mobile (Client Hints), touch support via 'ontouchstart' in window or navigator.maxTouchPoints > 0, viewport width via window.innerWidth, and CSS media queries with (hover: none) and (pointer: coarse). No single signal is 100% reliable alone.