sitekits.dev
press ⌘K to switch tools
NETWORK · HTTP

User Agent Parser

Parse user agent strings to detect browser and OS.

local
user-agent-parser
§01 ABOUT THIS TOOL

Overview

A User-Agent string is the browser’s self-description, and it is one of the least trustworthy fields in HTTP — partly because clients lie deliberately, and partly because thirty years of compatibility hacks have made every string claim to be several browsers at once.

This tool reports the browser and version, the operating system and version, a device class, and whether the string identifies itself as automated.

How to use

  1. Paste a User-Agent string. Your own is filled in on load.
  2. Read the browser, OS, device and bot verdict.

Why the detection order is the whole problem

Consider a Microsoft Edge string:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0

It claims to be Mozilla, AppleWebKit, Chrome, Safari and Edge. A parser that checks for Chrome first reports Chrome, and a very large amount of analytics data is wrong for exactly this reason.

The rule is to check the most specific token first. Edg/ before Chrome/, OPR/ before Chrome/, SamsungBrowser/ before Chrome/, and Chrome/ before Safari — because Chromium claims Safari too, while Safari does not claim Chrome.

The version number has to come from the specific token as well. Edge 120’s Chrome/120.0.0.0 is a Chromium version, not an Edge version, and they diverge.

Anatomy of the string

Reading a UA is easier once you know that almost every token is there for historical reasons rather than descriptive ones.

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
  • Mozilla/5.0 — every browser claims this. In the 1990s, servers checked for “Mozilla” before serving frames, so everyone started claiming it and nobody has ever been able to stop.
  • The parenthesised block — platform details. OS name and version, CPU architecture, and on mobile the device model. This is the part browsers are now truncating.
  • AppleWebKit/537.36 (KHTML, like Gecko) — frozen at 537.36 across all of Chromium since 2013. It is a constant, not a version. KHTML, like Gecko claims kinship with two more engines.
  • Chrome/120.0.0.0 — the Chromium major version. The minor components are deliberately zeroed.
  • Safari/537.36 — matches the WebKit token. Present so that code checking for Safari keeps working.

The useful information is in one or two tokens; the rest is compatibility sediment. A parser that treats the string as a description rather than as a layered set of claims will get it wrong.

Device classification

The device class is inferred from tokens, and the two signals that matter are counter-intuitive:

  • iPad sends Mobile. An iPad’s UA contains Mobile/15E148, so a check for Mobi matches it. Checking for iPad has to come first, or every tablet is reported as a phone.
  • Android tablets omit Mobile. Google’s convention is that the Mobile token is present on phones and absent on tablets. So an Android tablet is Android without Mobile — a negative test, which is easy to leave out.

This tool checks iPad, Tablet, and Android-without-Mobile before it checks the phone tokens, so tablets are classified as tablets.

What no parser can fix is the desktop-mode iPad. Since iPadOS 13, Safari on iPad sends a macOS string by default; the only reliable distinguisher is navigator.maxTouchPoints, which is not in the UA. If tablet detection matters to your application, read touch points client-side rather than parsing.

The string is shrinking on purpose

Browsers are actively reducing what the UA reveals, because the same detail that helps analytics also enables fingerprinting.

Chrome has frozen the minor version to 0.0.0 and reduced the OS version. Safari has reported a fixed OS version for years. navigator.platform is deprecated. The replacement is User-Agent Client Hints (Sec-CH-UA, Sec-CH-UA-Platform, Sec-CH-UA-Mobile), which sends a short set of values by default and requires the server to ask for anything more.

The practical consequence is that a UA parser gets less accurate over time, and that is intentional. Treat browser-major-version and OS-family as the durable signal, and treat anything more precise as a bonus that will eventually stop arriving. The browser fingerprint tool shows the other attributes that reduction is meant to protect.

Examples

  • Analytics that show impossible Chrome share. Check whether your parser puts Chrome before Edg. This single ordering bug moves several percent of traffic between browsers.
  • A support ticket with no reproduction. The OS and browser version from the reporter’s UA is usually enough to narrow it.
  • Filtering bots from logs. The self-identifying ones are easy; be explicit that the number is a floor and not a count.
  • Auditing an old browser-version gate. A version comparison written against a UA is already unreliable and gets worse with every reduction. Replace it with a feature check.

Notes

Version numbers with underscores — macOS and iOS report 10_15_7 — are normalised to dots. That formatting difference is purely cosmetic in the UA and carries no meaning.

Unknown means no pattern matched, which is a real answer for a string from a niche browser, an embedded WebView, an HTTP client library, or a spoofing extension producing an inconsistent combination.

The bot check looks for bot, crawl, spider, slurp, curl, wget, python and headless. It is a description of what the client admits to, not a security control. Anything that matters should be enforced with rate limits and a challenge server-side, because a UA is a string the client chooses. The privacy policy describes how the API on this site does it.

FAQ
Is the string sent anywhere?
No. Detection is regex matching in the page. Nothing leaves your browser, and the tool works offline once loaded.
Why does my Chrome UA also mention Safari and Mozilla?
Historical compatibility. Every browser claims to be Mozilla/5.0, Chromium-based browsers claim Safari for WebKit-era feature detection, and Edge, Opera and Samsung Internet all claim Chrome on top of that. The string is a stack of compatibility lies, which is why the parsing order matters more than the patterns.
Why is a modern iPad reported as macOS?
Because that is what it sends. Since iPadOS 13, Safari on iPad requests desktop sites by default and its UA is indistinguishable from a Mac's. The give-away is maxTouchPoints, which is not in the UA at all — so no UA parser can get this right.
Should I use this for feature detection in production?
No. Detect the feature, not the browser — `if ('share' in navigator)` rather than a version comparison. UA parsing is for analytics, support triage and log analysis, where you are describing traffic rather than deciding behaviour.
How reliable is the bot flag?
It catches honest bots and nothing else. Googlebot, curl and python-requests all identify themselves. A crawler that wants to blend in copies a real browser's string exactly, and no UA-based check will ever see it.