What is a user agent string?
Every browser and HTTP client sends a User-Agent header describing itself. For historical reasons these strings are long and confusing: nearly every browser claims to be "Mozilla/5.0", Chrome mentions Safari, and Edge mentions Chrome. This user agent parser reads the whole string and works out what the client really is.
Example
Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1Browser Mobile Safari 17.5
Engine WebKit 605.1.15
OS iOS 17.5
Device type mobile
Device Apple iPhone
CPU —
Bot / crawler no
What the user agent parser detects
- Browser and version – Chrome, Edge, Firefox, Safari, Opera, Samsung Internet and others, plus tools and libraries such as curl.
- Rendering engine – Blink, WebKit or Gecko.
- Operating system – Windows, macOS, iOS, iPadOS, Android, Linux distributions, Chrome OS and more, with versions where available.
- Device type – desktop, mobile, tablet, smart TV, console, bot, or a library/CLI client.
- Device vendor and model – for example Apple iPhone, or Samsung and Google Pixel models on Android.
- CPU architecture – amd64, arm64, arm or ia32 when the string reveals it.
- Bots and crawlers – Googlebot, Bingbot, social media preview fetchers, SEO crawlers and AI crawlers are flagged.
Reading a desktop Chrome user agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36Only two tokens really matter here: Windows NT 10.0; Win64; x64 (64-bit Windows 10 or 11) and Chrome/126.0.0.0. "AppleWebKit" and "Safari" are compatibility leftovers, and the minor version numbers are zeroed out on purpose to reduce fingerprinting. The parser reports this as Chrome 126 with the Blink engine on Windows 10/11, amd64.
Common uses
- Log analysis – paste user agents from access logs (up to 100 at once) to see which browsers and devices your visitors use.
- Bug reports – decode the user agent a customer sent to find their exact browser and OS version.
- Bot filtering – check whether suspicious traffic claims to be a crawler.
- Testing – verify that your own device detection logic agrees with an independent parser.
Batch parsing
Paste user agents from a log export, one per line, and each is parsed separately with a divider between results. That makes it easy to spot the unusual entries, such as outdated browsers or scripted clients, in a sample of traffic.
Limits you should know
- User agents can be faked. Any client can send any string, so a "Googlebot" user agent does not prove the request came from Google. Verify real crawlers with a reverse DNS lookup; the IP to hostname tool helps.
- Reduced user agents. Chrome and other browsers now freeze parts of the string: Windows 11 still reports "Windows NT 10.0" (shown here as Windows 10/11), macOS versions are frozen at 10_15_7, and Android device models may be replaced by "K". iPads usually request desktop sites with a Mac user agent. Newer detail is available through User-Agent Client Hints instead.
- Prefer feature detection. For deciding what your site should do, test for the feature (for example with
'share' in navigator) rather than the browser name.
To see your own browser's user agent, run navigator.userAgent in the JavaScript tester and paste the result here. Parsing happens entirely in your browser.
User agent parser in Python
The standard library has nothing for this, and matching substrings yourself goes wrong quickly: a Chrome user agent also contains Safari and AppleWebKit, so a test like "Safari" in ua misidentifies it. The user-agents package builds on the ua-parser rule set and returns the browser, operating system and device, plus the flags is_mobile, is_tablet, is_pc and is_bot. Parse the string once and read the attributes; the browser version is available as a tuple in version and as text in version_string.
# pip install user-agents
from user_agents import parse
strings = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
]
for s in strings:
ua = parse(s)
print(ua.browser.family, ua.browser.version_string, "|",
ua.os.family, ua.os.version_string, "|", ua.device.family,
"| mobile:", ua.is_mobile, "bot:", ua.is_bot)
# Chrome 126.0.0 | Windows 10 | Other | mobile: False bot: False
# Mobile Safari 17.5 | iOS 17.5 | iPhone | mobile: True bot: False
# Googlebot 2.1 | Other | Spider | mobile: False bot: True
For a single string from a log line, pasting it above is quicker, and it gives a second opinion when the library answers Other.