HTTP Headers Test

See the exact headers this browser sent to our server, what each one gives away, and whether the wire agrees with what the same browser tells JavaScript. Free, no signup.

  • One request to our server
  • Headers echoed back to you only
  • No signup

Sending one request and reading back what arrived…

Now give every account its own device.

A clean browser is still one browser. Sendwin runs each profile in isolation with its own fingerprint, cookies and proxy, so the accounts you work on never look like they came from the same machine.

  • Isolated profiles, each with its own fingerprint and cookies
  • A proxy per profile, with the timezone bound to the proxy country
  • Windows, macOS and Linux — plus cloud sessions when you need them

The free plan includes 10 minutes of cloud browsing a day.

A dozen answers before any script runs

Before a page runs a single line of JavaScript, the request that fetched it has already described the browser in a dozen headers: what it is, which languages it wants, which compression it understands, which operating system it runs on, how the request was triggered. A site does not have to ask for any of this. It arrives with every request, it is written by the browser rather than the page, and most of it is stable enough to recognise a browser by. This page sends one request to our server, reads back exactly what arrived, and explains each header in a line.

The more useful half is the comparison. Everything a header says can also be asked of JavaScript — navigator.userAgent, navigator.language, navigator.userAgentData — and a real browser answers both questions from the same place. When an extension rewrites the User-Agent header but not the JavaScript property, or a proxy strips Client Hints that the API still exposes, the two channels disagree, and that disagreement is worth more to a detection system than either value on its own. The second table on this page runs those comparisons. Any proxy headers that arrived with the request are listed in a third.

Two channels, one browser

Headers travel on the wire; properties live in the page. A browser fills both from one internal state, so on an unmodified install the User-Agent header and navigator.userAgent are identical to the character, the first entry of Accept-Language is navigator.language, and the sec-ch-ua brand list matches navigator.userAgentData.brands exactly. Most tools that change a browser's identity change only one channel. Header-rewriting extensions and proxies touch the wire and leave the page alone; JavaScript overrides do the reverse. A site that reads both, on the same request, does not have to guess which one was edited — it only has to notice that they differ.

The headers that identify a browser

User-Agent is the obvious one, and Accept-Language is nearly as specific: the ordered list of languages plus their weights is set from the operating system and rarely matches between two people. Accept-Encoding gives the browser family away by which compressions it lists and in what order. The low-entropy Client Hints — sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform — are sent by every Chromium build without being asked, and their placeholder brand is generated from the major version, so a hand-edited list stands out. Newer builds add a Priority header and, on Firefox, a TE header that Chromium never sends. None of these is secret. The point is that they all have to agree with each other and with the page.

What a proxy adds, and one honest caveat

A forwarding proxy may add Via, X-Forwarded-For or Forwarded on the way through. The page lists any that reached the server, with the edge's own bookkeeping already removed, and reduces them to a verdict: transparent when another public address was forwarded, anonymous when a proxy announced itself without one, and direct when nothing arrived — which covers both a plain connection and a proxy that adds nothing. The caveat: the request this page sends is a script fetch, not a page navigation, so Accept, Sec-Fetch-Mode and Sec-Fetch-Dest describe that fetch. User-Agent, the languages, the encodings and the Client Hints are identical on both kinds of request, and those are the ones that identify you.

What the page does

  1. 1

    Send one request

    The page fetches a small endpoint on our server with the same headers your browser attaches to every request. Nothing else is sent, and nothing is stored.

  2. 2

    Read what arrived

    The server echoes an allow-listed set of the request headers back to the page that sent them — never cookies, never authorisation — with the proxy headers separated out.

  3. 3

    Ask JavaScript the same questions

    The page reads navigator.userAgent, navigator.language and navigator.userAgentData here and sets each beside its header. Disagreements are listed field by field.

HTTP headers FAQ

Which headers every request carries, why the wire and the page have to agree, and what the server keeps.

On every request: User-Agent, Accept, Accept-Language, Accept-Encoding and the fetch-metadata headers that say how the request was made. Chromium adds the three low-entropy Client Hints on every request and the high-entropy ones only when a server has asked. Depending on settings you may also see Do Not Track, Global Privacy Control, and a Priority header. The first table lists exactly what reached our server from this browser.

Because a browser writes both from one value. There is no configuration in Chrome, Firefox or Safari that makes the User-Agent header differ from navigator.userAgent; the only way they diverge is that something rewrote one of them. A site does not need to know what the real value is to score that — it only needs to see two answers to one question.

That a header arrived carrying a public address other than the one the connection came from. The proxy forwarded the address behind it, so the site sees you and the proxy at once. For anything that needs the two kept apart, that is the worst outcome a proxy can produce, and it is set by the proxy's configuration rather than by anything in the browser.

Because this request was made by the page's script, and a script fetch asks for anything. A navigation — typing an address, clicking a link — sends text/html first with a list of image formats that differs by browser. Those two headers, along with Sec-Fetch-Mode and Sec-Fetch-Dest, describe the request rather than the browser, which is why the page does not treat them as identifying.

By every Chromium build — Chrome, Edge, Opera, Brave, Samsung Internet and the rest — but not by Firefox or Safari, and not by any browser on iOS, where everything is WebKit. A request carrying sec-ch-ua while claiming Firefox was assembled by hand, and the comparison table says so.

No. The endpoint reads the request, sends the allow-listed headers back to the page that made it, and keeps nothing. Cookies and authorisation headers are never echoed. The response is marked uncacheable so no intermediary can replay one visitor's headers to another.

Each profile's user agent, languages and Client Hints are set once, at the engine level, so the wire and the page always answer from the same identity — there is no header rewrite for a site to catch. Open this page inside a profile and the comparison table reads all pass.

Still have questions? Talk to us →

What agreement does and does not mean

The comparison is between two channels of one browser on one request. Agreement means the header and the page were produced from the same values; it does not mean those values describe the machine, and it does not rank this browser against any other. The request the page sends is a script fetch, so a few headers describe the fetch rather than the browser, and the table labels those.

Headers that never have to be rewritten.

Sendwin sets each profile's user agent, languages and Client Hints at the engine level, so the wire and the page always answer from one identity. Free for 30 days on Windows, macOS and Linux.

Signed Windows & macOS builds · patched-Chromium engine · EU & US cloud nodes

30-day free trial · $0 today · cancel anytime — your profiles stay on your machine

Try in the cloud →Start free trial