How User Agent Strings Actually Work
The HTTP User-Agent header is one of the strangest artifacts of web history. Here's what it actually contains, how browsers and bots identify themselves, and what UA-based detection really costs in 2026.
Anatomy of a modern UA string
Take a typical Chrome on macOS:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/124.0.0.0 Safari/537.36
That single line contains five claims, none of which are exactly true:
- Mozilla/5.0 — historical prefix; means nothing today.
- (Macintosh; Intel Mac OS X 10_15_7) — the OS family, plus a frozen version (Apple stopped advancing this for privacy).
- AppleWebKit/537.36 (KHTML, like Gecko) — the rendering engine, claiming compatibility with KHTML and Gecko.
- Chrome/124.0.0.0 — the actual browser, with a zeroed-out minor version (also privacy-driven).
- Safari/537.36 — a Safari compatibility token, because some sites still gate on it.
Why every browser claims to be Mozilla
In 1995, Netscape (Mozilla) shipped frames. Web servers started sending the frames version of pages only to UAs starting with Mozilla/. When Internet Explorer added frame support, Microsoft prefixed its UA with Mozilla/ to qualify — and added the real identifier later as a "compatible" token. Every browser since has done the same thing. The web's compatibility story is written in the UA string.
Detecting devices, bots and crawlers
Mobile vs desktop
The reliable signal is the literal substring Mobile in Chrome/Safari UAs, plus form-factor tokens like iPhone, iPad and Android. Don't rely on screen size — desktop browsers can be narrow, and tablets can be wide.
Bots and crawlers
Well-behaved bots identify themselves clearly:
Googlebot/2.1 (+http://www.google.com/bot.html)
Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)
Look for bot, crawler, spider, or a +http URL pointing to the operator. Verify with reverse DNS — anyone can claim to be Googlebot.
Headless browsers and scrapers
Default Puppeteer leaks HeadlessChrome; default Playwright leaks nothing in the UA but exposes itself through navigator.webdriver. Sophisticated scrapers spoof real UAs, which is why UA-based bot detection alone is never enough.
Privacy implications
The UA string is a passive fingerprinting vector. Combined with screen resolution, timezone, language and installed fonts, it routinely identifies an individual browser. Browsers have responded by:
- Freezing OS version strings (Safari, Chrome).
- Reducing Chrome's minor version to
0.0.0. - Shipping User-Agent Client Hints — a structured replacement (
Sec-CH-UA,Sec-CH-UA-Platform) where the browser decides what to expose.
If you're building new server-side logic, prefer Client Hints. Treat the legacy UA as a coarse hint, not a fact.
What to actually do with the UA header
- Analytics: aggregate by browser/OS family for capacity planning.
- Progressive enhancement: serve a polyfill to old engines.
- Bot triage: deprioritize obvious crawlers in expensive endpoints.
What not to do:
- Never gate security features on UA.
- Never block a browser by version range — the next minor update will break your site.
- Never trust the UA to determine device capabilities. Use feature detection instead.
FAQ
Why does Chrome's User Agent contain the word Mozilla?
Mozilla/. Every browser since has kept the prefix to avoid being downgraded.Can I trust the User Agent header?
What is User-Agent Client Hints?
Sec-CH-UA-* headers and decide what to share with each origin.How do I verify Googlebot is really Googlebot?
googlebot.com or google.com, then forward-resolve that hostname back to the original IP.