What Is a User Agent? Reading UA Strings, Client Hints and User-Agent Reduction

Every app that talks to a web server introduces itself, usually without the person using it ever noticing. That introduction travels in a single request header, and developers, analytics tools and server logs all lean on it. Proxy users run into it as well: a request sent through a residential proxy still carries whatever label the client chose, because the proxy changes the network path rather than the header. This explainer covers what the label is, how to read it, what Client Hints add, and why modern browsers deliberately say less than they used to.

What is a user agent, exactly?

Three things share one name. The user agent is the software acting for a person: a browser, a command-line tool, a mobile app or a crawler. User-Agent is the HTTP request header that software sends. The user-agent string is the value inside that header.

MDN describes the header as a characteristic string that lets servers and network peers identify the application, operating system, vendor and version of the requesting software. Its grammar is simple: one or more product tokens, each with an optional version, plus comments in parentheses. Keep the three layers apart in bug reports; “the user agent was wrong” rarely tells a colleague which layer failed.

How to read a user-agent string

Browser strings look intimidating because they carry decades of compatibility baggage. Here is the Windows desktop Chrome example that MDN publishes:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Token What it really says
Mozilla/5.0 Historical marker sent by almost every browser
(Windows NT 10.0; Win64; x64) Reported platform comment, not verified hardware
AppleWebKit, KHTML, like Gecko Compatibility wording, not extra engines
Chrome/143.0.0.0 Product and major version; minor parts zeroed
Safari/537.36 One more compatibility token

Read from the right for the actual product and treat everything else as context. Edge appends Edg/, Opera appends OPR/, and Chrome on iPhone uses CriOS/. Libraries are far plainer: curl sends curl/ plus its version. Default to matching the most specific token you need, never the first one.

Firefox follows a different shape. Its strings carry an rv: value for the Gecko release, then Gecko/20100101 on desktop and finally Firefox/ with the browser version. Safari, by contrast, puts a Version/ token before the WebKit build, and on iPhone, other browsers still sit on WebKit, so their strings resemble Safari’s. Parsing rules written for one family rarely survive contact with the others.

Client Hints: the structured alternative

User-Agent Client Hints split that blob into separate fields. Chrome’s developer guide says they have been enabled by default since Chrome 89, and that the browser sends three basic hints on every request: Sec-CH-UA with brands and significant versions, Sec-CH-UA-Mobile, and Sec-CH-UA-Platform. Anything more detailed, such as the full version list, platform version, architecture or device model, has to be requested by the server with an Accept-CH response header, and the browser applies its own policy before answering.

That ask-first model is the point. Servers stop receiving everything by default, and code stops relying on fragile regular expressions. Pages can also read the same data through navigator.userAgentData in JavaScript. Prefer Client Hints whenever you need one specific field, and fall back to the user-agent string only for clients that do not send them.

Why a modern phone can report an old Android version

Here is the counter-intuitive part of user-agent reduction. MDN shows that Chrome on Android now reports a fixed platform of Android 10 and a fixed device model of K, while minor version numbers appear as zeros. Even a current flagship on the latest release can therefore claim Android 10. The goal is privacy: detailed strings made it easy to fingerprint individual users.

WebView is following. An EZXLabs explainer on the topic notes that the Android Developers WebView announcement names Android 17 as the starting version for default-string reduction in in-app browsers. Audit any rule that extracts device models or patch versions from the string. Default to Client Hints for those details unless a report only needs broad categories like “mobile” or “desktop”.

Common confusion: the label is not the person, the IP or the proxy

Clients choose their own label, so it is a claim rather than an identity. Network addresses are observed separately by the server and never come from this header. Proxies sit on a different layer again.

Take a rotating residential proxy as an example. In rotating mode, the EZXLabs backconnect gateway assigns a new IP to each request, yet every one of those requests carries the identical user-agent string your client sent. A sticky session keeps one exit for a fixed 10-minute TTL, but your browser still has to preserve cookies and login state. Through an HTTPS or SOCKS5 tunnel, the proxy relays encrypted bytes and does not read the header at all.

Equally, a self-chosen bot name isn’t an authentication credential. Naming a script after a well-known crawler grants none of that crawler’s permissions, and sites that care verify crawlers by other means.

Legitimate uses for developers and analytics

Grouping traffic is the classic job. Analytics tools parse the string into browser families and device classes, which is fine for reporting trends and spotting when an old browser still matters to your audience. Describe those categories as reported, not verified.

Debugging is the second. When one client fails and another works, the header often reveals that the failing request came from a library default, an outdated app build or an in-app browser. Server logs that keep the full string make these cases quick to isolate. Traffic that passes through a residential proxy follows the same rule: a rotating or sticky session changes the address your server sees, not the label your code set, so check the client configuration first when the value looks wrong.

Building your own client is the third. Give it an honest, readable label such as ExampleClient/1.0, ideally with a contact address in a comment, so site owners can recognise and reach you. For layout and features, MDN’s guidance is to test the capability you need instead of guessing support from a browser name; use the string for coarse grouping only.

Check which User-Agent a server actually received

Configuration, the request a client prepared, and what the receiver logged are three different observations. The 3-View User-Agent Check compares all three for the same request before anyone declares a mismatch. In the source walkthrough, six local HTTP checks ran on October 21, 2026, using curl 8.21.0 and Requests 2.34.2: curl’s -A option and a Requests headers argument each set the value, an empty -A "" removed the header entirely, and a per-request header overrode the session default.

Browser checks work the same way. Open DevTools, select the Network tab, pick one request and read Request Headers; navigator.userAgent in the Console shows the JavaScript-facing value, which can differ. If you want to reproduce the full set, the walkthrough answering what is a user agent includes the local echo receiver and every command used.

Limits, compliance and a short checklist

Changing a header is ordinary client configuration, and native header configuration needs no paid service. What it must not become is disguise. Do not borrow a crawler’s or a competitor’s identity, and do not use labels to slip past bot protection or terms of service. Robots rules describe requested crawling behaviour, not access control, so authorized collection still means respecting robots.txt, site terms, rate limits and personal-data law. EZXLabs, for its part, sells residential proxy traffic and is not a scraper or extraction API. When a plan’s traffic runs out, its gateway returns HTTP 429 with EZP_QUOTA_DENIED, and no user-agent change affects that.

  • Name the layer: software, header or string.
  • Match the most specific product token, not the first.
  • Request Client Hints for details the reduced string no longer carries.
  • Treat platform and model values as reported, not verified.
  • Compare configuration, prepared request and receiver log for the same request.
  • Send an honest label from your own tools and never impersonate another client.
Simon

Leave a Reply

Your email address will not be published. Required fields are marked *