A User-Agent string is the text your browser puts in the HTTP User-Agent request header to announce what it is — the browser, its rendering engine, the operating system, and often the device — so the server can decide what to send back. A typical Chrome-on-Windows value looks like Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36. It is defined in RFC 9110, sent on essentially every request, and — critically — fully controlled by the client, so it can be changed to say anything. That last fact is why you should treat it as a hint, never as proof.
That is the summary an AI Overview will give you. Here is what it can't show you: why that string is a museum of 30-year-old compatibility hacks, how to read each token, exactly how servers parse it, and why the whole mechanism is being dismantled in favor of Client Hints. Below is a labeled anatomy of a real UA, an animated request/parse flow, a token cheat-sheet, and a decision guide for when (rarely) UA detection is still the right call.
Anatomy of a real User-Agent string
Every modern desktop UA follows the same skeleton, and almost none of it means what it literally says. Here is the Chrome example above, dissected token by token:
The single most important takeaway: the only token that reliably names the browser is the vendor token near the end (Chrome/120, Firefox/121, Edg/120, OPR/106). Everything to its left is a compatibility ritual. Note also that Edge appends Edg/120 after Chrome/120, and Opera appends OPR/106 — order matters when you parse, because a naive "contains Chrome" check will misclassify both.
How a server actually uses the User-Agent
The header travels with the request, the server (or a reverse proxy in front of it) reads it, runs it through a parser library, and branches on the result. Here is the round trip:
The parsing itself is almost never done by hand. Regex-parsing UA strings yourself is a well-known trap — the format has no strict grammar, tokens appear in vendor-specific orders, and new device strings ship weekly. Use a maintained library (ua-parser-js, woothee, device-detector) that ships a regularly-updated regex database, or paste a string into our client-side parser to see the fields broken out:
Token cheat-sheet: what each part means
When you do need to read a UA by eye, this table covers the tokens you will actually encounter.
| Token | Appears in | What it really means | Trust it? |
|---|---|---|---|
Mozilla/5.0 | Every browser | Frozen legacy prefix from the Netscape era. Says nothing. | No — ignore |
Windows NT 10.0 | Windows browsers | OS platform + version. NT 10.0 = Windows 10 and 11 (they share it). | Mostly — coarse |
Macintosh; Intel Mac OS X 10_15_7 | macOS browsers | Frozen at 10_15_7 on modern Safari/Chrome to limit fingerprinting. | Version is fake now |
AppleWebKit/537.36 | Chrome, Edge, Safari | Rendering-engine claim. Frozen number; Chrome uses Blink, not WebKit. | No |
(KHTML, like Gecko) | Chromium browsers | Pure compatibility padding. | No — ignore |
Chrome/120.0.0.0 | Chrome + Chromium | The real browser + major version. Minor digits now zeroed out. | Yes (major only) |
Edg/120.0.0.0 | Microsoft Edge | Edge marker, appended after Chrome/. Note: Edg, not Edge. | Yes |
OPR/106.0.0.0 | Opera | Opera marker, appended after Chrome/. | Yes |
Version/17.0 Safari/605 | Safari | Version/ holds Safari's real version; Safari/605 is the engine build. | Yes |
Firefox/121.0 + rv:121.0 | Firefox | rv: = Gecko engine revision; Firefox/ = browser version. | Yes |
Mobile | Phone browsers | Hints a mobile viewport. Easily absent or faked. | Weak signal |
bot, crawler, spider | Bots | Well-behaved crawlers self-identify (Googlebot, bingbot). Malicious ones lie. | Only for good bots |
When should you use User-Agent detection at all?
UA sniffing has a bad reputation because it is overused. Most of what people reach for it to do is better solved another way. Use this to decide:
| Goal | Use the User-Agent? | Better approach |
|---|---|---|
| Change layout for phones vs desktop | No | CSS media queries + responsive design |
| Check if a browser supports a feature | No | Feature detection (if ('IntersectionObserver' in window)) |
| Detect mobile server-side | Rarely | Sec-CH-UA-Mobile Client Hint (clean boolean) |
Serve the right OS-specific download (.dmg vs .exe) | Yes | Platform token or Sec-CH-UA-Platform |
| Analytics: which browsers do my users run | Yes | Parse UA (or Client Hints) into aggregate stats |
| Block or throttle known bad bots | Partly | UA is one signal; combine with IP reputation + behavior |
| Access control / licensing / security gate | Never | The UA is client-controlled and trivially spoofed |
The rule of thumb: UA detection is fine for optimization and analytics, and wrong for anything that must be correct or secure. If a wrong answer merely means a suboptimal layout, sniffing is acceptable. If a wrong answer means a security bypass or a broken feature, use detection or Client Hints instead.
The future: User-Agent Client Hints
Browsers are actively shrinking the classic UA because it is a fingerprinting liability — that one string leaks enough entropy to help identify individual users. The replacement is User-Agent Client Hints (UA-CH): instead of one bloated string, the browser exposes structured, opt-in headers.
Sec-CH-UA— brand + significant version list, e.g."Chromium";v="120", "Google Chrome";v="120"Sec-CH-UA-Mobile— a boolean,?0or?1Sec-CH-UA-Platform—"Windows","macOS","Android", etc.
Low-entropy hints (brand, mobile, platform) are sent by default. High-entropy hints (full version, exact model, architecture) are sent only when a server asks via the Accept-CH response header. Chrome has already "reduced" its UA string so minor versions and device details are stripped; Firefox and Safari froze large chunks of theirs years ago. The practical implication: any code that pattern-matches specific version numbers or device names out of the UA is on borrowed time — migrate to Client Hints, which are documented in our guide to handling User-Agent Client Hints in modern browsers.
Key takeaways
- A User-Agent string identifies the client in the HTTP
User-Agentheader (RFC 9110), and the client fully controls it — treat it as a hint, never as proof of identity. - Most of the string is legacy compatibility theater; the vendor token near the end (
Chrome/,Firefox/,Edg/,OPR/) is the only reliable browser name. - Parse with a maintained library, not hand-rolled regex, and send
Vary: User-Agentwhenever the response depends on it so CDNs don't serve the wrong variant. - Prefer feature detection and CSS media queries over sniffing; reserve UA logic for OS-specific downloads and analytics.
- The classic UA is being frozen and reduced in favor of structured Client Hints (
Sec-CH-UA*) — migrate version- and device-specific logic accordingly.
Paste any string into our User-Agent parser to break it into browser, engine, OS, and device fields — all client-side, nothing sent to a server.