User-Agent Generator: Current Strings That Are Not Stale
Runs in your browser — nothing you enter here is sent to us.
A string claiming a browser version that was retired three releases ago is a flag, not a disguise. These are built from your own browser's version wherever we can read it, so they stay current without anyone maintaining a list.
Versions taken from your own browser (), so they are current by definition. We cannot read a version for this family off your browser, so this one uses our own table, last checked by hand in . Check the current release before using it anywhere that matters.
generated
A desktop template is one exact string — real browsers of the same version and platform all send the same thing, and varying it would make yours the odd one out. The mobile templates vary their OS version and model, which real devices genuinely do.
Built in your browser from templates in the page. Nothing is requested and nothing is sent — the generator works with the connection unplugged.
Why a generated user agent is usually the wrong fix
It is worth saying this before the tool rather than after it. Replacing your user agent string is the first thing people try when a scraper starts getting blocked, and on its own it rarely helps — because the string is the cheapest thing a site reads and almost never the only thing.
A request arrives carrying a user agent, a set of headers in a particular order, TLS handshake parameters specific to the client library, and, if JavaScript runs, several dozen browser values. Claiming to be Chrome on Windows while your HTTP library sends its own header order and its own TLS fingerprint produces a request that matches no real browser — which is a better signal for a blocker than a plain, honest python-requests/2.31.0 would have been.
Where a current, correct user agent does matter is the opposite case: you are running a real browser, everything else about the request is genuine, and the string is the one stale value. That happens more than you would expect, because strings get pasted into a config once and then run for two years.
How this generator stays current
This is the part most generators get wrong. A hard-coded table of versions is accurate the week it ships and quietly wrong a month later, and a string claiming a Chrome version that was retired three releases ago is a flag rather than a disguise. Chrome ships a major version roughly every four weeks.
So the version numbers here are read from your own browser wherever we can read them. If you are on Chrome, the Chrome templates use the version you are actually running, which is current by definition and needs no maintenance from us. The same goes for Firefox, Edge and Safari. Only when we cannot read a family off your browser — asking for Firefox strings while browsing in Chrome — does the page fall back to a table we maintain by hand, and it says so plainly, with the date it was last checked, instead of pretending to be fresh.
Why the desktop templates do not vary
You may notice that asking for ten Chrome-on-Windows strings gives you one. That is deliberate, and it is the opposite of what most generators do. Every real Chrome on 64-bit Windows of a given version sends a byte-identical user agent — the string carries no machine-specific detail at all. A generator that varied the minor version or shuffled the tokens would produce ten strings that no browser has ever sent, each of which is individually more suspicious than the real one.
The mobile templates do vary, because real devices do: the Android version and the model string genuinely differ from handset to handset, and a pool of Android agents that are all identical is as odd as a pool of desktop agents that are all different.
Where the string shows up, and where it does not
"Changing your user agent" means different things in different places, and the places do not always agree with each other — which is itself one of the ways a mismatch is detected.
- The User-Agent header. Sent with every request, including for images and stylesheets. This is the one an HTTP library sets and the only one a server sees if no JavaScript runs.
- navigator.userAgent. Read by scripts in the page. An extension that changes the header but not this property creates a contradiction that one line of JavaScript will find — and plenty of extensions do exactly that.
- Client Hints. A set of separate headers (Sec-CH-UA and relatives) that current Chromium browsers send alongside the string. They carry the brand, version and platform in a structured form, and they are where Chrome has been moving the detail it removed from the string. Spoofing the string while Client Hints tell the truth is a common and easily-detected inconsistency.
- Nowhere at all, for TLS. The handshake happens before any header is sent, and its parameters identify the client library independently of anything you set. This is why a Python request claiming to be Chrome is caught before the user agent is even read.
The short version: setting the string in one place and not the others produces a client that matches nothing real. If you are using a browser, change it with something that changes all of them; if you are using a library, accept that the string is the least of it.
Using them without making things worse
- Match the platform to everything else. A macOS string from a machine with a Windows font set and Windows client hints is a contradiction, and the fingerprint reader will show you which values would give it away.
- Do not send a mobile string from a desktop connection. An iPhone agent with a 2560×1440 screen, no touch support and a datacentre address is specific enough to look deliberate.
- Rotate across devices, not across versions. If you need a pool to look varied, vary the platform and the device. Three Chrome versions on identical hardware is not variety, it is a browser mid-update.
- Re-generate periodically. Whatever you paste into a config today goes stale on the same four-week cycle as everyone else's. If you take the strings from your own browser here, coming back after a few updates gives you current ones.
- Fix the rest of the request first. If you are scraping with an HTTP library rather than a browser, the header order and the TLS fingerprint matter more than the string. Use a client that imitates a browser at that level, or run a real browser.
To check what a string you already have actually claims — including whether its version is one anybody still runs — paste it into the user-agent parser.
User-agent generator: questions we get
Why does asking for ten desktop strings give me one?
Because every real Chrome on 64-bit Windows of a given version sends exactly the same string — it carries no machine-specific detail. Ten varied strings would be ten strings no browser has sent, each more suspicious than the real one. The mobile templates do vary, because real devices genuinely differ.
Are these version numbers current?
Where we can read your own browser's version, yes, by definition — the Chrome templates use the Chrome you are running. For a family we cannot read off your browser, the page falls back to a table we maintain by hand and tells you when it was last checked.
Will changing my user agent stop me being blocked?
On its own, usually not. The string is the cheapest thing a site reads and almost never the only thing: header order, TLS fingerprint and several dozen browser values are all checked too. A Chrome string from a Python HTTP library matches no real browser and is a better signal than an honest one.
Is anything sent to you when I generate?
No. The templates are in the page and the strings are built in your browser. The generator works with the connection unplugged.
Can I use these for a scraper?
You can, and they will be correct strings. Whether that helps depends on the rest of the request — if you are using an HTTP library rather than a browser, fix the header order and the TLS fingerprint first, because those are checked more often than the string.
Should every request in a pool use a different user agent?
Vary the platform and device rather than the version. Several versions of the same browser on identical hardware looks like a browser mid-update, not like several people. And two hundred requests sharing one byte-identical string is the easiest pattern there is to block.