User-Agent Parser: What Your Browser Is Telling Every Site
Runs on our server — the value you submit is processed and not stored.
Every browser's introduction is thirty years of compatibility fossils stacked on each other — which is why Chrome claims to be Safari, and why parsing one by hand goes wrong. This reads yours properly.
That is a declared bot: ClaudeBot
AI Data Scraper, run by Anthropic PBC. A string like this one announces what it is rather than pretending to be a browser — which is why it gets served robots.txt rules instead of a CAPTCHA.
Parsed on our server with the Matomo device-detector ruleset. The string is read and the result rendered; nothing is written down.
Why user-agent strings look like that
Your browser introduces itself with a line like this:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Read literally, that claims to be Mozilla, and also AppleWebKit, and also KHTML, and also Chrome, and also Safari. It is nonsense, and it is nonsense for a reason: every one of those tokens was added so that servers checking for a competitor would serve the good version of the page. Netscape called itself Mozilla. Internet Explorer called itself Mozilla so it would be served Netscape's pages. Safari claimed KHTML because it was a KHTML fork. Chrome claimed Safari. Edge claims Chrome. Thirty years of that is what the string has become — a compatibility fossil nobody can remove because too much server code still reads it.
Which is why parsing one by hand goes wrong. The obvious regex for Chrome matches Edge, Opera, Brave, Vivaldi and most of Android's in-app browsers. The obvious regex for Safari matches every Chromium browser in existence. Getting it right means a maintained ruleset with thousands of entries and a known order, and that is what this page uses.
What this parser does
It reads the string on our server with the Matomo device-detector ruleset — the same engine behind a large share of self-hosted web analytics — and splits the answer into the client, the operating system and the device. It starts with your own browser's string, because the one you can check against reality is the fastest way to learn to read the next one.
Paste any string to parse it instead. Three results are worth knowing how to read:
- A recognised browser. The name, version, engine, platform and, on mobile, the make and model.
- A declared bot. Googlebot and its relatives say what they are rather than pretending to be Chrome. That honesty is why they get robots.txt rules instead of a CAPTCHA.
- Nothing recognised. This is a result, not a failure. No shipping browser sends that string, and a site checking user agents will reach the same conclusion and block it. If you assembled the string by hand for a scraper, you have just found your problem.
A dash against a field means the string does not carry that information. That is increasingly normal: Chrome has been deliberately reducing what its user agent reveals, moving the detail into Client Hints, which are separate headers. A parser cannot invent what the string does not say, and one that fills the gaps with plausible guesses is worse than one that admits them.
The string, token by token
It is worth reading one all the way through once, because afterwards every other string in this family becomes obvious. Taking the Chrome example above:
- Mozilla/5.0 — means nothing. Every browser sends it. It is there because 1990s servers checked for it before serving a page with frames.
- (Windows NT 10.0; Win64; x64) — the platform block. Windows NT 10.0 covers both Windows 10 and Windows 11: Microsoft did not change the token, so no user agent can distinguish them.
- AppleWebKit/537.36 (KHTML, like Gecko) — frozen. Chromium forked from WebKit in 2013 and the version has not moved since. It is a fossil, and a string that "updates" it is a string no browser sends.
- Chrome/131.0.0.0 — the real information. Note the zeroes: Chrome stopped reporting its minor version, so only the major number is meaningful.
- Safari/537.36 — another fossil, matching the WebKit version above.
Firefox is the readable one by comparison — Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0 — where rv: and the Firefox token agree and Gecko/20100101 is a fixed date that has not meant anything since 2010. Edge appends Edg/131.0.0.0 to an otherwise complete Chrome string, which is why reading it as Chrome is the standard parsing mistake.
Where this matters if you are using proxies
The user agent is the cheapest thing a site checks and the cheapest thing to get wrong. Four mistakes account for most of the blocks:
- A version that no longer exists. Scrapers get a user agent pasted in once and then run for two years. Chrome ships a major version every four weeks, so a string that was current when it was written is, by now, a version nobody is running. That is a sharper signal than sending no user agent at all.
- A user agent that contradicts everything else. Claiming Safari on macOS while your browser sends Chromium's client hints, Chrome's header order and a Windows font set. Any one of those is checked more often than the string itself.
- A mobile user agent from a desktop connection. An iPhone string arriving over a datacentre address, with a 2560×1440 screen and no touch support. The contradiction is trivial to detect and it is specific enough to be deliberate.
- The same string across an entire pool. Two hundred addresses sending one byte-identical user agent is a pattern, and it is the easiest kind of pattern to block, because one rule catches the lot.
If you need current strings rather than a parse, the user-agent generator builds them from your own browser's version, which keeps them from going stale. And the string is only one of the values a site reads — the fingerprint reader shows the rest, which is where most of the contradictions live.
User-agent parser: questions we get
Why does my Chrome user agent mention Safari and Mozilla?
Compatibility history. Every token was added so that servers sniffing for a competitor would serve the good version of the page: IE claimed Mozilla, Safari claimed KHTML, Chrome claimed Safari, Edge claims Chrome. Nobody can remove them because too much server code still reads them.
Is my user agent sent anywhere?
It is read on our server to parse it, and that is all — nothing is written down. Your browser already sends its user agent with every request to every site, including this one, so there is nothing here it has not already told us.
What does a dash in a field mean?
That the string does not say. Chrome deliberately reveals less than it used to and has moved the detail into Client Hints, which are separate headers and not part of the string you pasted. A parser that filled those gaps with guesses would be worse than one that admits them.
The parser did not recognise my string. Is it broken?
That is the result, not a failure. No shipping browser sends an unrecognised string, and a site checking user agents will treat it exactly the same way. If you built the string by hand for a scraper, this is the problem you came to find.
How accurate is the device detection?
Good for anything mainstream and weaker for the long tail of Android devices, which is inherent: the model is only identifiable if the vendor put it in the string and the ruleset knows that model. Desktop browsers do not identify the machine at all, by design.
Should I change my user agent to avoid being blocked?
Only to one that is current and consistent with everything else you send. A stale version, or a mobile string from a desktop connection, is a stronger signal than the default would have been. Changing it in isolation usually makes you more conspicuous, not less.