User Agent Parser
Parse user agent strings to detect browser and OS.
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
- Paste a User-Agent string. Your own is filled in on load.
- 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 Geckoclaims 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 containsMobile/15E148, so a check forMobimatches it. Checking foriPadhas to come first, or every tablet is reported as a phone. - Android tablets omit
Mobile. Google’s convention is that theMobiletoken is present on phones and absent on tablets. So an Android tablet isAndroidwithoutMobile— 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
ChromebeforeEdg. 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.