User-Agent: what the client says it is
User-Agent identifies the client software making the request. The strings are historically messy, increasingly frozen, and a poor basis for deciding what to send back.
At a glance
- Direction
- Request only. The response counterpart is Server.
- Defined in
- RFC 9110
- When absent
- The request is still perfectly valid. Many command line tools and scripts send nothing at all.
- Shape
- A list of product tokens with optional comments, most of them historical fiction
- Being reduced
- Chrome and others freeze parts of the string to cut fingerprinting.
- Modern alternative
- Client hints, where the client sends specific facts on request
- Cache impact
- Vary: User-Agent effectively disables shared caching.
In detail
Every mainstream browser claims to be Mozilla, and most also claim some relationship to another engine. That is not deception so much as accumulated compatibility: each generation added tokens so that servers sniffing for the previous generation kept working. The result is a string that cannot be parsed reliably and that no specification constrains beyond a loose grammar.
Browsers are now actively reducing it. Chrome freezes the version and platform details it exposes, and the direction of travel is a short, mostly static string plus client hints for anything a site genuinely needs. Code that extracts a minor version number from the string is therefore working against a value that is deliberately becoming less informative.
For deciding what to serve, feature detection in the page beats parsing this header, because it tests the actual capability rather than a claim about identity. The legitimate server side uses are narrower: rough analytics, blocking abusive automated clients, and serving a genuinely different asset for a platform that cannot be detected any other way.
For your own clients, set something honest. A request from a script or a service that identifies the application and a contact address makes you a good citizen when your traffic shows up in somebody else's logs, and it is often the difference between being rate limited and being contacted.
Examples
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36Almost every token here is historical. Only the Chrome version carries current information, and even that is being reduced.
User-Agent: ReportSync/1.4 (+https://example.com/bots; ops@example.com)Accept-CH: Sec-CH-UA-Platform-Version
Sec-CH-UA-Platform-Version: "14.2.1"Things that catch people out
- Blocking requests with no User-Agent catches plenty of legitimate scripts and monitoring probes along with the traffic you meant to stop.
- Version number comparisons on the string break every time a browser changes its format, and the formats are changing on purpose.
- Varying a cached response on this header creates a variant per browser build, which in practice means no shared caching at all.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →Server: what software answered the request
What the Server header conveys, why exposing a version number helps attackers narrow their targets, and what to put there instead of removing it entirely.
Vary: which request headers change the response
How Vary extends a cache key, why Vary: User-Agent destroys hit rates, what Vary: * means, and the CORS case where forgetting Vary: Origin causes real bugs.
Accept: asking for a media type, with preferences
How the Accept header expresses preferences with q values, how servers pick a representation, and what to return when nothing on the list can be produced.
X-Forwarded-For: the client address behind a proxy
How the X-Forwarded-For list is built, why the leftmost address is not trustworthy, how to count trusted hops, and what breaks rate limiting behind a proxy.
Access-Control-Allow-Origin: who may read this response
How the allow origin header is matched, why a wildcard fails with credentials, why it takes only one origin, and why Vary: Origin is mandatory when you echo.
Access-Control-Allow-Methods: permitted methods on preflight
Where the allow methods header belongs, why it appears only on the preflight response, which methods never need it, and how it interacts with caching.
Tools for this
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL