Blog

How to parse user agent strings (browser, OS, device)

How a user agent string is built, how to tell browsers, devices and bots apart, and where user agent parsing stops being reliable.

February 7, 2026

Your analytics say 12% of visitors use Safari on a Mac, but the support inbox is full of iPad screenshots. Or a "browser" has requested your pricing page 40,000 times since lunch. Either way, the user agent string is where you start digging, and it's a stranger thing than it looks.

What a user agent is

A user agent string is a line of text that a client, usually a browser, sends in the User-Agent header of every HTTP request. It names the application, its version and the operating system it runs on. Servers use it for analytics, for serving different content to different clients, and for spotting bots.

In theory that's simple. In practice, 30 years of browsers pretending to be other browsers have made these strings long, inconsistent and full of misleading tokens. That's why it's worth knowing how they're built before you write a parser.

Structure of a user agent string

A current Chrome user agent on Windows looks like this:

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

Broken into its parts:

TokenMeaning
Mozilla/5.0Historical compatibility token sent by almost every browser
(Windows NT 10.0; Win64; x64)Platform: 64-bit Windows. Windows 11 also reports NT 10.0, so the string can't tell 10 and 11 apart.
AppleWebKit/537.36Engine token, kept for compatibility (Chrome uses Blink)
(KHTML, like Gecko)More compatibility claims
Chrome/120.0.0.0Browser and major version. Chrome now reports only the major version and zeros.
Safari/537.36Safari compatibility token

Why so much noise? In the early web, sites often served their best pages only to browsers they recognised. Each new browser copied the tokens of the popular ones so it wouldn't get the lesser version. The result is that Chrome introduces itself as Mozilla, WebKit, Gecko and Safari before admitting it's Chrome.

Detecting the browser

The order of checks matters, because many browsers include the tokens of the browser they are built on:

Text
Chrome:  Mozilla/5.0 ... Chrome/120.0.0.0 Safari/537.36
Firefox: Mozilla/5.0 ... Gecko/20100101 Firefox/121.0
Safari:  Mozilla/5.0 (Macintosh; ...) AppleWebKit/605.1.15 ... Version/17.2 Safari/605.1.15
Edge:    Mozilla/5.0 ... Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
Opera:   Mozilla/5.0 ... Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0

Edge and Opera are Chromium-based and include Chrome/, so check for Edg/ and OPR/ first and fall back to Chrome. Every Chromium browser also includes Safari/, so only treat a string as Safari when it has no Chrome/. Safari’s own version is in the Version/ token. Some browsers, such as Brave, send exactly the same string as Chrome and can't be told apart from the user agent alone.

Detecting bots and crawlers

Search engines and other crawlers send their own user agents:

Text
Googlebot: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Bingbot:   Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
GPTBot:    Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.0; +https://openai.com/gptbot
Script:    python-requests/2.31.0

Spotting bots keeps your analytics honest and helps with rate limiting and security. Well-behaved bots name themselves and link to documentation. Anyone can copy those strings, though, so verify important crawlers another way: Google and Bing support a reverse DNS lookup on the requesting IP. Malicious bots usually send an ordinary browser user agent, so the string alone won't catch them.

Mobile, tablet or desktop

Mobile browsers usually include the word Mobile and a platform such as iPhone or Android. Android tablets typically leave out Mobile.

Text
iPhone Safari:  Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 ... Mobile/15E148 Safari/604.1
Android Chrome: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 ... Chrome/120.0.0.0 Mobile Safari/537.36

Two caveats. Since iPadOS 13, Safari on iPad sends a desktop Mac user agent by default, so most iPads look like Macs. And Chrome on Android now reports a fixed Android 10; K instead of the real version and device model.

Because user agents carry less detail than they used to, Chromium browsers offer User-Agent Client Hints (Sec-CH-UA headers and navigator.userAgentData) as a structured alternative. For layout, prefer CSS media queries and feature detection over user agent sniffing.

How to use the user agent parser

  1. Open the user agent parser and paste a string from your logs, or select Use my user agent to fill in your current browser’s.
  2. Select Parse. The result shows the browser and version, the operating system and version, the device type and the rendering engine.
  3. Select Copy to copy the result as JSON.

A few details about what the parser reports:

  • Browsers detected: Microsoft Edge, Opera, Chrome, Safari and Firefox. Anything else shows as Unknown.
  • Operating systems detected: Windows (with the version name, such as 7, 8.1 or 10/11), macOS, iOS, Android and Linux.
  • Engines: Blink, WebKit or Gecko.
  • Device type is Mobile, Tablet, Desktop or Bot. A string is marked as a bot when it contains bot, crawler, spider or crawling, so scripts such as python-requests show as Desktop.

It's useful for checking analytics discrepancies, testing bot detection rules and making sense of server logs. Parsing happens in your browser.

Need data from a webpage as JSON?

PulpMiner turns any public page into structured JSON and can save it as a live API. See it work on a demo page, no sign-up.

Try it on a demo page