User-Agent Parser
Paste a User-Agent string and see the browser, engine, OS, and device behind it.
Or try a sample:
This does not look like a User-Agent string
Nothing in the text matched a known browser, engine, operating system, or bot token. Check for a truncated paste,
a stripped-down UA sent by a custom HTTP client, or a deliberately spoofed value. A real User-Agent almost always
contains a product token like Chrome/126.0.0.0 or a platform hint like Windows NT 10.0.
What this string is hiding
Parsed result (JSON)
Your browser’s navigator.userAgentData
The User-Agent Client Hints API — the structured replacement for the UA string.
Notice the deliberately fake entries in brands — Chromium ships a randomised
“GREASE” brand such as Not/A)Brand on every request specifically to break
naive string matching, so that developers are forced to write forward-compatible checks instead of exact-match lists.
No Client Hints here.
Your browser does not expose navigator.userAgentData. It is a Chromium-only API today —
Firefox and Safari have both declined to implement it, citing fingerprinting concerns. That is the main reason the
classic User-Agent string is still with us.
How to Use the User-Agent Parser
- Paste a User-Agent string into the box — from a server access log, an analytics export, a request header, or a bug report.
- The breakdown updates live as you type. No button to press, no request sent.
- Click Use my browser’s User-Agent to load your own
navigator.userAgentvalue. - Use the sample buttons to see how Chrome, Safari, Edge, Opera, Googlebot and curl each identify themselves.
- Copy the structured result as JSON to paste into an issue, a test fixture, or a spreadsheet.
Everything runs in your browser. The string you paste is never uploaded anywhere.
What is a User-Agent String?
A User-Agent is a header your browser attaches to every HTTP request. It is a single line of free-form text whose job is to tell the server what software is asking for the page. A typical modern example looks like this:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Read it left to right and it is a list of product tokens, each optionally followed by a slash and a version, with comments in parentheses. In principle it identifies one browser. In practice, the example above names four different products — Mozilla, AppleWebKit, KHTML and Safari — none of which are actually running.
Why Every Browser Claims To Be Mozilla (And Safari, And KHTML)
This is the single strangest thing about User-Agent strings, and it is entirely the product of thirty years of accumulated compatibility hacks. Each layer was added because servers were sniffing for the previous one.
- Mozilla/ — Netscape Navigator called itself
Mozillain 1994. Sites started serving frames only to Mozilla. When Internet Explorer arrived it supported frames too, so it declared itselfMozilla/1.22 (compatible; MSIE 2.0; ...)to get the good content. Every browser since has kept the prefix. TodayMozilla/5.0is a hardcoded constant that carries no information at all. - KHTML, like Gecko — Apple built WebKit from KDE’s KHTML engine, and needed sites that sniffed for Gecko (Firefox) to serve it modern markup. So Safari claimed to be KHTML-based and Gecko-like simultaneously.
- Safari/ — when Chrome launched in 2008 it used WebKit, and sites were already sniffing for Safari to serve
WebKit-friendly CSS. Chrome therefore appended
Safari/537.36. Chrome switched to its own Blink engine in 2013 and kept the token anyway. It has been a lie for over a decade. - Chrome/ in Edge and Opera — Microsoft Edge and Opera are Chromium browsers, so they include a
Chrome/token and append their own marker at the end:Edg/andOPR/. Note that Edge usesEdg, deliberately without the trailing “e”, so that code sniffing for the old EdgeHTML-based “Edge” does not match.
The practical consequence for anyone writing a parser: detection order is everything. Check for
Edg/, OPR/ and SamsungBrowser/ before Chrome, and check for Chrome before Safari. Get the order backwards and every Edge user in your
analytics is silently counted as Chrome.
The Browsers That Are Not What They Say
On iOS and iPadOS, Apple’s App Store rules have historically required every browser to use the system WebKit engine. Chrome, Firefox, Edge and Opera on an iPhone are all WebKit under the hood — they are essentially skins over Safari with their own sync, UI and bookmarks. They signal themselves with distinct tokens:
CriOS/— Chrome on iOS (WebKit, not Blink)FxiOS/— Firefox on iOS (WebKit, not Gecko)EdgiOS/— Edge on iOS (WebKit, not Blink)OPiOS/andOPT/— Opera and Opera Touch on iOS
This matters far more than a logo in a dashboard. If a CSS feature or a JavaScript API is broken in Safari, it is broken in
every browser on that device. A parser that reports “Chrome 126” for a CriOS string
will send you hunting for a Blink bug that cannot exist. This tool reports the engine separately from the brand for exactly
that reason.
Why UA Sniffing Is Discouraged
Branching your code on the User-Agent string is one of the oldest anti-patterns on the web. The string is trivially editable — every browser has a device-emulation mode, every HTTP client lets you set the header, and privacy extensions spoof it by default — so it is not a security control and it is not reliable telemetry. Worse, a UA check is a snapshot of the world on the day you wrote it. New browsers and new versions ship constantly, and code that says “if not Chrome, show the fallback” will keep punishing browsers that gained the feature years ago.
The recommended alternative is feature detection: ask the browser whether the thing you need actually works,
rather than guessing from its name. Test the capability directly with checks like
"IntersectionObserver" in window, CSS.supports("display", "grid"),
or typeof navigator.share === "function". These stay correct forever, cannot be spoofed into
the wrong answer, and work for browsers that did not exist when you shipped.
Legitimate uses for parsing a UA do remain: aggregate analytics, reproducing a bug from a support ticket, serving the right app store badge, filtering crawlers out of your logs, and rate-limiting abusive clients. Those are all after-the-fact reporting rather than runtime branching — which is exactly the right place for it.
Client Hints: The Replacement
Because the UA string leaks a lot of passively-collected entropy useful for fingerprinting, Chromium has been shrinking it
under a programme called User-Agent Reduction. Desktop UA strings now report a frozen minor version, and
Android strings report a frozen Android 10 with the device model masked as
K — which is why a modern Pixel can show up as an anonymous Android 10 handset.
What replaces it is User-Agent Client Hints: the same information, but structured, requested explicitly, and
split into low-entropy and high-entropy tiers. In JavaScript it is
navigator.userAgentData, exposing brands,
mobile and platform for free, and platform version, architecture,
bitness, model and full browser version only via an async
getHighEntropyValues() call. On the server, the same data arrives as
Sec-CH-UA headers, and you must opt in with an
Accept-CH response header before the high-entropy ones are sent.
The catch is adoption. Client Hints are Chromium-only — Firefox and Safari have both declined to implement them on fingerprinting grounds. So for the foreseeable future you need both: Client Hints where available, and a careful, correctly ordered UA parser everywhere else.
Specifications
- Accepts
- Text — type or paste
- Gives you
- copy to clipboard
- Where it runs
- Your browser — the file is never uploaded
- Sign-up
- None
- Cost
- Free, with no usage limits
FAQ
Why does Chrome say it is Safari and Mozilla?
Pure historical compatibility. Mozilla/5.0 dates back to Netscape in 1994 and was copied by Internet Explorer to receive frame-capable pages; every browser has kept it since, and it now carries no information at all. The Safari token was added when Chrome launched on WebKit in 2008, because sites already sniffed for Safari to serve WebKit-friendly CSS. Chrome moved to its own Blink engine in 2013 but kept the token so those sites would not break. The KHTML and like Gecko fragments are the same trick one layer further back.
Can a User-Agent string be trusted?
No. It is a plain request header that anyone can set to anything. Browser devtools let you override it in one click, every HTTP library exposes it as a parameter, privacy extensions randomise it, and plenty of bots impersonate Googlebot outright. Treat it as a hint for analytics and debugging, never as authentication, access control, or proof of who is calling you.
How do I detect mobile devices properly?
Do not use the UA string for layout. Use CSS media queries for viewport size, pointer and hover media queries such as (pointer: coarse) to detect touch-first input, and navigator.maxTouchPoints if you need it in JavaScript. These describe the actual capability you care about and keep working when a phone is rotated, a tablet is docked to a keyboard, or a laptop has a touchscreen. UA-based mobile detection fails on all four.
What is the difference between a browser and a rendering engine?
The browser is the product you install — Chrome, Edge, Safari, Firefox. The engine is the code that actually parses HTML and CSS and paints the page: Blink for Chromium browsers, WebKit for Safari and everything on iOS, Gecko for Firefox, and the retired Trident, EdgeHTML and Presto for old Internet Explorer, old Edge and old Opera. For debugging a rendering bug the engine is the thing that matters, which is why this parser reports both separately.
Why does my Android phone show as Android 10 with model K?
That is Chrome User-Agent Reduction. To cut down on passive fingerprinting, Chrome on Android now freezes the reported OS version at 10 and replaces the device model with the letter K for all users. Nothing is broken — the real values are simply no longer in the string. If you genuinely need them, request them through User-Agent Client Hints with getHighEntropyValues, which requires an explicit call and, server-side, an opt-in header.
Is the string I paste sent to your server?
No. The entire parser is JavaScript that runs in this page. There is no network request, no analytics event carrying the string, and no npm parsing library loaded from a CDN. You can disconnect from the internet and the tool will still work.