Understanding User-Agent strings
A string that lies to you, on purpose.
Why every browser pretends to be every other browser, what the User-Agent fields actually mean, and the modern replacements that aren't yet universal.
The User-Agent is theatre.
A typical Chrome User-Agent looks like: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36. Chrome claims to be Mozilla, claims to be AppleWebKit, claims to be like Gecko, claims to be Safari. Why? Because servers in the 1990s sniffed User-Agent strings and served degraded HTML to "Mozilla"-shaped browsers; every new browser had to claim to be Mozilla to get the good content. The lies compounded; nobody has been able to clean them up since.
What a parser extracts.
A User-Agent parser pattern-matches against the cluttered string and extracts four pieces: browser (name + version), engine (Blink, Gecko, WebKit), operating system (Windows, macOS, Linux, iOS, Android — with version), and device type (desktop, tablet, mobile, sometimes specific model). The information is real; the encoding is just messy. Mature libraries like ua-parser-js maintain regex sets that catch ~99 % of real-world strings.
A worked parse.
From Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1: browser = Safari 17.4, engine = WebKit, OS = iOS 17.4, device = iPhone (mobile). The same string carries it all if you know what to look for.
One UA, four facts
iPhone + iOS 17.4 + Safari 17.4 + WebKit
Each token in the UA contributes to one of the four extracted facts.
Mozilla → ignored ; iPhone → device ; iOS 17_4 → OS ; Safari 17.4 → browser
= Structured client info
Don't make decisions on the UA.
Server-side or client-side branching based on UA — "if Chrome, do this; if Safari, do that" — is the path to permanent technical debt. The right pattern is feature detection (does the browser support this API?) rather than browser detection (is this Chrome?). Browsers ship features at different paces; same name across versions is the norm. Even Apple's own UA spoofing shifts which "Safari" your code might be running on.
User-Agent Client Hints.
The replacement Google is pushing: User-Agent Client Hints, a set of structured headers (Sec-CH-UA, Sec-CH-UA-Platform, Sec-CH-UA-Mobile, etc.) that carry browser identity without the legacy theatre. The server requests specific hints with Accept-CH; the browser supplies them. Chrome ships them; Safari and Firefox are slower. The transition is years long; existing User-Agent strings will stay forever as a fallback.
What a parser is good for.
Analytics (knowing the rough mix of OS / browser / device in your audience). Bug triage (the same crash on iOS Safari 16 might not exist on iOS Safari 17). Telemetry aggregation (counting unique-ish device categories without storing identifying data). Detecting bots (well-known crawler UAs are recognisable). Not good for: serving different content per browser, gating features by browser identity, measuring detailed device capability — feature detection wins each of those.