UUID Studio

User-Agent Parser

Decode a User-Agent string into browser, OS, and device type.

  • 🔒 No data stored or uploaded
  • âš¡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Create or edit JSON here (syntax colors), then format, validate, or convert - same as MongoDB $binary UUID blobs on the Convert tab once detected.

New document

About User-Agent Parser

A User-Agent string is a historical artefact that has accumulated fragments for thirty years. A current Chrome UA still begins 'Mozilla/5.0' and mentions both AppleWebKit and KHTML and Safari and Gecko, none of which describes what the browser is. Every one of those tokens was added so that some server's sniffing code would not serve a degraded page, and they have been retained ever since because removing them breaks things.

That history is why parsing is unreliable rather than merely awkward. The order and presence of tokens is convention, not specification, so any parser is a pile of regular expressions matched against known strings - and it therefore fails on new browsers, unusual devices and anything deliberately spoofing.

It is also being actively reduced. Chrome's User-Agent Reduction now freezes the minor version numbers and generalises the platform string, so the UA no longer carries the detail it used to. The replacement is Client Hints: low-entropy headers such as Sec-CH-UA and Sec-CH-UA-Mobile are sent by default, and higher-entropy values like the full version or the model must be requested explicitly with Accept-CH. Any new detection work should use those rather than parsing.

The broader point is that UA sniffing is usually the wrong technique. If you need to know whether a feature exists, test for the feature; if you need to adapt to screen size, use a media query. The legitimate remaining uses are analytics, correlating a bug report with a specific build, and working around a known defect in a specific version - and even those should be treated as approximate.

Parsing runs in your browser and nothing is transmitted.

How to use the User-Agent Parser

  1. Paste a User-Agent string - from a log, a bug report, or your own navigator.userAgent.
  2. Read the detected browser, engine, operating system and device.
  3. Treat the result as a best guess, particularly for anything unusual or recent.
  4. If you are building detection rather than diagnosing, use Client Hints or feature detection instead.

Examples

  • Chrome on Windows
    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
  • Safari on iPhone
    Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1

User-Agent Parser in code

The same operation this tool performs, in the languages you are most likely to need it.

Client Hints - the modern approach
// Low-entropy hints, available synchronously
navigator.userAgentData?.brands;     // [{brand, version}, ...]
navigator.userAgentData?.mobile;     // boolean
navigator.userAgentData?.platform;   // "macOS", "Windows", ...

// High-entropy values must be requested and are async
const info = await navigator.userAgentData?.getHighEntropyValues([
  "platformVersion", "architecture", "model", "fullVersionList",
]);

// Server side: ask for the hints you need
//   Accept-CH: Sec-CH-UA-Platform-Version, Sec-CH-UA-Model
// then read them from subsequent requests:
//   Sec-CH-UA: "Chromium";v="120", "Google Chrome";v="120"
//   Sec-CH-UA-Mobile: ?0
//   Sec-CH-UA-Platform: "macOS"

// userAgentData is Chromium-only - Firefox and Safari have not
// implemented it, so a UA fallback is still needed.
Feature detection instead of sniffing
// Don't do this - version checks rot, and spoofing defeats them
if (/Chrome\/1[0-9][0-9]/.test(navigator.userAgent)) { /* ... */ }

// Do this - ask whether the capability exists
if ("IntersectionObserver" in window) { /* ... */ }
if (CSS.supports("display", "grid")) { /* ... */ }
if (navigator.share) { /* ... */ }

// For layout, use a media query, not a device guess
matchMedia("(max-width: 600px)").matches;
matchMedia("(hover: hover) and (pointer: fine)").matches;   // real mouse

// Legitimate UA use: working around a KNOWN bug in a known build,
// with a comment saying when it can be removed.
Anatomy of a UA string
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) \
  AppleWebKit/537.36 (KHTML, like Gecko) \
  Chrome/120.0.0.0 Safari/537.36
# ^ "Mozilla/5.0"  - meaningless, present in every modern browser
# ^ "(Macintosh; Intel Mac OS X 10_15_7)" - platform, now frozen by
#   Chrome's UA reduction regardless of the real macOS version
# ^ "AppleWebKit/537.36 (KHTML, like Gecko)" - frozen legacy tokens
# ^ "Chrome/120.0.0.0" - the only genuinely useful part; the minor
#   version digits are now always zero
# ^ "Safari/537.36" - present so old Safari-sniffing code works

# Test with a specific UA
curl -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ..." https://example.com

When you need this

  • Identifying which browser and version produced an error in your logs.
  • Correlating a bug report with a specific build.
  • Checking whether traffic is coming from a bot or a real browser.
  • Understanding what a UA string from an analytics export actually means.

Common problems and what causes them

Every UA string can be trivially spoofed
It is a client-supplied header with no verification. Any bot, script or user can set it to anything. Never use it for access control, licensing or anything security-relevant.
Version sniffing that rots
A check for Chrome/1[0-9][0-9] stops working at version 200, and a check for "Safari" matches Chrome too, since Chrome includes the token deliberately. Feature-detect instead.
Chrome's User-Agent Reduction removing detail
Minor version digits are frozen at zero and the platform version is generalised, so a UA no longer tells you the precise OS or build. Code depending on that detail now gets a frozen value rather than an error.
userAgentData not existing in Firefox or Safari
The Client Hints JavaScript API is Chromium-only. Code that reads navigator.userAgentData without a guard throws or silently does nothing in other browsers.
Assuming mobile means small
A tablet UA may report mobile with a screen larger than a laptop's, and desktop mode on a phone reports desktop. Use media queries for layout and pointer/hover queries for input capability.
Treating a parse result as authoritative
Parsers are regex libraries matched against strings they have seen before. New browsers, embedded webviews, smart TVs and bots are regularly misidentified. Treat the output as a probable answer.

FAQ

Why does every browser's User-Agent start with Mozilla/5.0?
For backwards compatibility with 1990s servers that checked for 'Mozilla' before serving frames. Every browser added the token so it would not be served a degraded page, and none has been able to remove it since. The same applies to the AppleWebKit, KHTML, Gecko and Safari fragments.
Can I trust the User-Agent string?
No. It is a client-controlled header that anyone can set to anything, so it is fine for analytics and diagnostics and unusable for anything that needs to be reliable.
What are Client Hints and should I use them?
A set of Sec-CH-UA headers, plus navigator.userAgentData, designed to replace UA parsing. Low-entropy hints are sent automatically; higher-entropy ones must be requested with Accept-CH. Prefer them for new work, but note the JavaScript API is Chromium-only, so keep a UA fallback.
How do I detect mobile devices reliably?
You mostly should not detect devices at all. Use media queries for layout, (hover: hover) and (pointer: fine) for input capability, and feature detection for APIs. Device detection by UA misclassifies tablets, webviews and desktop-mode phones.
Why is my Chrome version showing as 120.0.0.0?
User-Agent Reduction freezes the minor version digits at zero. If you genuinely need the full version, request it as a high-entropy Client Hint via getHighEntropyValues or Accept-CH.
Can a User-Agent string be trusted for security decisions?
No - a User-Agent header is just a string the client sends and can be freely changed by the user or a script. Treat it as a hint for analytics or UX, never as an authentication or authorization signal.
Why does Safari's UA string also mention 'like Gecko' and other engines?
Browsers have historically added other engines' names to their UA strings for compatibility with sites that only checked for specific tokens - it's legacy noise, not a sign the browser actually uses multiple engines.

Related reading