How to test if your browser is leaking (60-second test)
Having a proxy on does not mean you are protected. In 60 seconds you can run the fingerprint checker, review user agent, canvas, WebGL, fonts, WebRTC and your TLS handshake JA3/JA4, and know exactly what is leaking — without relying on what the anti-detect tool promises in its marketing.
Having a proxy on does not mean you are protected. In about a minute you can run four checks that cover every layer a website reads — the JavaScript surface, the WebRTC side channel and the TLS handshake underneath both — and find out exactly what your browser is handing over, instead of trusting what a tool promises on its landing page.
Why "I use a proxy" does not mean "I am protected"
A proxy changes exactly one thing: the IP address the server writes in its logs. It sits between your machine and the destination and forwards packets. That is the whole job, and it is a useful job — but it covers one of three layers a modern detector reads.
- Network layer. Public IP, the network that owns it, the country and city it geolocates to, and whether that network has a history of automated traffic. This is the layer a proxy replaces.
- Transport layer. The TLS handshake — the very first packet your browser sends, before a single byte of HTML arrives. It carries a fingerprint of its own, summarised as JA3 and JA4. A proxy forwards it untouched.
- Application layer. HTTP headers, Client Hints, and everything a page can read through JavaScript: canvas, WebGL, fonts, audio, screen, timezone, language, hardware. A proxy never sees this data, let alone changes it.
The failure mode is not that a detector spots "a proxy". Millions of ordinary people sit behind corporate networks, carrier-grade NAT and VPNs. What gets flagged is a contradiction: an IP that geolocates to São Paulo while the system timezone says America/New_York, the locale says en-US, and the WebGL renderer reports a GPU that does not exist on the operating system your user agent claims to be running. Nothing there is illegal or even unusual on its own. Together, they describe a device that could not exist.
How do you test if your browser is leaking?
Four checks, in this order, because each one covers a layer the previous check cannot see. Run the fingerprint checker for the JavaScript surface and the coherence cross-references, test WebRTC on its own because it bypasses the proxy through a different transport, inspect the JA3/JA4 of your handshake because JavaScript cannot reach it, and then read the four results as one story rather than four scores.
One rule before you start: run the test twice. Once in your everyday browser, once in the profile you actually work in. The difference between the two reports is the value your setup is adding. Without that baseline you are reading numbers with nothing to compare them to, and a good-looking score means very little.
Step 1 — run the fingerprint checker
Open the fingerprint checker inside the profile you use for work — not the window you are reading this in. That distinction matters more than it sounds: most people test the browser they browse in, get a clean report, and never test the environment where the accounts actually live.
The page reads what any website can read without asking permission: the navigator object (user agent, platform, vendor, languages, logical CPU count, device memory), the screen block (resolution, colour depth, device pixel ratio), the Intl timezone, a canvas hash, the WebGL vendor and renderer strings, the installed font list, an AudioContext hash, the WebRTC candidates and the Client Hints your browser advertises.
Write down three values before moving on — you will need them in the later steps: the public IP and its country, the reported timezone, and the canvas hash. Everything else you can read on screen.
Step 2 — read the result: user agent, canvas, WebGL, fonts
A score at the top of a report is a summary, not a diagnosis. These four blocks are where the actual contradictions live.
User agent versus platform versus Client Hints
Three fields have to tell the same story. The user agent string names an operating system; navigator.platform should match it (Win32 for Windows, MacIntel for macOS, Linux x86_64 for Linux); and the Client Hints headers (Sec-CH-UA, Sec-CH-UA-Platform) should report the same brand and the same major version. A user agent claiming Chrome 131 on Windows while Client Hints stay silent is a Chromium that had its string edited and nothing else. This is the single most common failure in home-made setups, and it is covered in depth in our piece on why changing the string is not enough.
Canvas: you want stable, not blocked
The instinct is to want the canvas "blocked". That is the wrong target. Reload the checker three times and watch the hash. Inside one profile it should be identical on all three reloads and different from your other profiles. A hash that changes on every read means the tool is injecting fresh random noise per call, and no physical machine behaves that way — the instability becomes a signature of its own.
WebGL: a plausible GPU for the claimed OS
The checker reads the unmasked vendor and renderer strings. What matters is whether that GPU could exist on the platform you are claiming. A renderer string in the ANGLE (Intel, Intel(R) UHD Graphics ... Direct3D11 ...) shape is Windows — Direct3D does not exist on macOS or Linux. Apple Silicon reports an Apple GPU. llvmpipeor a Mesa software renderer says "virtual machine with no GPU passthrough" loudly enough that some platforms treat it as a signal by itself.
Fonts: the OS gives itself away
Font enumeration is one of the oldest and most stable fingerprinting vectors, and one of the easiest to get wrong. A Windows profile with no Segoe UI or Calibri, a macOS profile with no Helvetica Neue, or a profile that claims macOS while listing fonts that only ship with Windows — each one is a contradiction that costs nothing to detect.
Step 3 — test WebRTC separately
WebRTC deserves its own step because it does not travel the same road as your page traffic. It negotiates a peer connection over UDP with its own address discovery, and an HTTP or SOCKS proxy configured in the browser does not automatically carry it.
The mechanism is simple. RTCPeerConnectionasks a STUN server "what address do you appear to come from?". The answer comes back as a server-reflexive candidate. If that UDP packet left through your real network interface, the candidate contains your real public IP — while the page itself was loaded through the proxy. The page and the peer connection disagree, and the site sees both.
.local. Seeing one of those in the candidate list is normal and expected. The value that matters is the public one: compare it with your proxy IP. Same address, you are fine. Different address, you are leaking.Run the WebRTC leak test and then decide how to handle it. There are five common treatments, and they are not interchangeable: block (no candidates gathered at all), fake (a synthetic address consistent with the proxy), real (pass through untouched — only correct if your proxy actually carries UDP), forward (route the peer connection through the proxy), and disable-UDP (force ICE over TCP only). The full trade-off between them is in our deep dive on WebRTC leaks.
Step 4 — check the JA3/JA4 of your handshake
Before any HTML, before any header, before JavaScript exists, your browser opens the connection with a TLS ClientHello. That message lists the TLS version, the cipher suites it supports and in what order, the extensions, the supported elliptic curves and the ALPN protocols. Different browsers build that list differently, and the list is a fingerprint.
JA3 hashes those fields in the order they appear. It worked well until Chrome started randomising the order of its TLS extensions from version 110 onwards, which makes the JA3 of a real Chrome change from connection to connection — noisy on its own, but still useful in aggregate.
JA4 is the successor and fixes exactly that. It sorts the cipher and extension lists before hashing them, so the randomisation no longer matters, and it keeps a readable prefix instead of one opaque hash: a fingerprint like t13d1516h2_... reads as TLS over TCP, TLS 1.3, 15 cipher suites, 16 extensions, ALPN negotiated to HTTP/2. Two of those fields alone already separate browser families.
What you are looking for is agreement: the JA4 your handshake produces should be the one a real Chrome of the major version in your user agent produces. A browser that says Chrome 131 in its string and emits a handshake belonging to no shipped Chrome is describing a device that does not exist.
What is normal to expose and what is not
Not every visible value is a problem. Trying to hide all of them creates a rarer profile than leaving them alone. Use this as the reading key for your report:
| Signal | Normal | Red flag |
|---|---|---|
| Public IP | Proxy IP, geolocating where you expect | Real ISP IP while the proxy is on |
| Timezone | Matches the IP country | UTC, or a country away from the IP |
| Language / locale | Plausible for the IP country | en-US on a residential IP in Brazil, for a local account |
| Canvas hash | Stable per profile, unique across profiles | Changes on every reload |
| WebGL renderer | A GPU that exists on the claimed OS | Direct3D strings on macOS, or a software renderer |
| Fonts | The set that ships with the claimed OS | Empty list, or fonts from a different OS |
| WebRTC public candidate | Matches the proxy IP, or none at all | A different public IP than the page traffic |
| navigator.webdriver | Absent or false | true |
| Client Hints | Same brand and major as the user agent | Missing on a Chrome user agent |
| JA4 | Matches a real Chrome of the same major | Belongs to no shipped browser |
What to do if the test came back bad
Fix in order of blast radius, and fix one thing at a time. The temptation after a bad report is to change six settings at once, rerun, and see green — at which point you have no idea which change did the work or whether one of them made something else worse.
- Real IP exposed through WebRTC. Highest priority, because it undoes the proxy entirely. Set the WebRTC mode on the profile and retest.
- Timezone or locale disagreeing with the IP country. Cheap to fix, expensive to ignore — it is the contradiction that automated checks catch first.
- User agent, platform and Client Hints out of sync. Change them as a set, never the string alone.
- Unstable canvas or audio hash. You want a fixed seed per profile, not fresh randomness per call.
- TLS handshake that matches no real browser. The hardest to fix by configuration, because it is a property of the browser binary, not of a setting.
If you want to run this same sequence in an environment built around it, the desktop version of AlterAntiX is free and every profile opens on an internal diagnostic page that runs these checks before you navigate anywhere. Download it here and compare the two reports side by side — your normal browser against an isolated profile. That comparison is the honest test, and it takes about a minute.
- A proxy replaces the IP and nothing else — two of the three layers travel untouched.
- Test twice: your everyday browser first, the work profile second. The delta is the answer.
- Stable and coherent beats hidden. A value that changes on every read is its own signature.
- WebRTC and TLS need their own checks — one bypasses the proxy, the other is invisible to JavaScript.
- Change one setting, rerun, compare. Never six at once.
Frequently asked questions
Does a good VPN pass this test?
It passes the IP part and fails the rest. A VPN swaps your exit address exactly like a proxy does, and never touches canvas, WebGL, fonts, timezone, Client Hints or the TLS handshake. Run the test with the VPN on and you will see the IP change while the rest of the report stays identical to your normal browser.
My canvas hash changes on every reload. Is that good?
No. Inside one profile the hash should be stable across reloads and different from every other profile. A hash that changes on every call means random noise with no fixed seed, and that instability is itself a signal: no real machine returns a different canvas every time it is read.
Is blocking WebRTC always the safest option?
It is the safest against IP leaks and the least common among real users. A browser where RTCPeerConnection returns no candidates at all is unusual on a consumer desktop. On platforms where video calls are routine, a WebRTC that is masked and consistent with the proxy usually draws less attention than a dead one.
Can I check JA3 and JA4 on a JavaScript-only site?
You cannot. The TLS handshake happens before any JavaScript exists on the page, and the browser does not expose its own ClientHello to scripts. Only the server that received the handshake can compute your JA3/JA4, which is why this check needs a tool with a server-side component.
How often should I re-run the test?
Whenever you change proxy, update the browser or the anti-detect tool, spin up a new batch of profiles, and at the first sign of friction (repeated identity checks, captcha loops, dropped sessions). Version updates are the most forgotten trigger: they change the user agent and can silently misalign the TLS preset.
Does AlterAntiX pass its own test?
Every profile launched in AlterAntiX lands on an internal diagnostic page that runs the same checks and shows the score before you browse anywhere. No tool scores perfectly against every detector, and anyone promising that is selling. What you can verify is coherence: IP, timezone, locale, Client Hints and handshake telling the same story.
Fingerprint and TLS, actually aligned
AlterAntiX matches the browser fingerprint with the TLS handshake on the same Chrome version. Download and test it yourself.
Download AlterAntiX