JA4+ and TLS Fingerprints: How Sites Identify Browsers at the Network Layer

10 min read

Most writing about browser fingerprinting is about JavaScript: canvas, WebGL, audio, fonts. There is another layer that is computed earlier and that no page script can see or change. It is the TLS handshake, and the fingerprint built from it, JA3 and now JA4+, is one of the main ways a server tells what kind of client is connecting.

This guide explains what the handshake contains, how JA4+ summarises it, why a proxy does not alter it, and what that means for anyone who cares about a consistent browser identity: site owners, QA testers, privacy-minded users and teams who keep separate profiles for accounts they are entitled to hold. For the JavaScript side, see our overview of browser fingerprinting.

See your own values first. We built a public checker at justbrowser.app/fingerprint-checker, client-side with no signup. It compares your WebRTC candidates against your public IP and checks whether the IP's location has a UTC offset that agrees with your browser's timezone. Run it before you read on.

What the TLS handshake contains

When a browser connects to a site over HTTPS, its first message is a "Client Hello". It carries:

  • Cipher suites: the encryption algorithms the client supports, in order of preference
  • TLS extensions: features such as SNI, ALPN, signature algorithms and supported groups
  • Protocol versions: TLS 1.2, TLS 1.3 or both
  • Compression methods: almost always null today, but still part of the message

All of this is sent before the page loads and before any JavaScript runs. The server sees it whether or not it ever serves a page. The details differ between browser families and between releases, so the handshake says something about what software is on the other end.

From JA3 to JA4+

JA3 was the first widely used way to summarise a Client Hello. It hashed the cipher suites, extensions and elliptic curves into one string. It had two weaknesses. Different software could collide on the same hash, and reordering extensions, which many modern clients do on purpose, changed the hash without changing the software.

JA4+ was released in 2023 by FoxIO, founded by one of JA3's creators. Rather than one opaque hash, it produces a structured fingerprint made of readable parts plus truncated hashes. A JA4 value looks like t13d1516h2_8daaf6152771_b0da82dd1658:

  • The first segment is human-readable: the protocol (t for TCP), TLS 1.3, SNI present, 15 cipher suites, 16 extensions and h2 for HTTP/2 as the first ALPN value.
  • The second segment is a truncated hash of the sorted cipher suites.
  • The third is a truncated hash of the sorted extensions.

Sorting makes the hash robust to extension reordering, which is the improvement over JA3. The wider JA4+ family includes related fingerprints for other protocol layers, such as JA4H for HTTP requests, which looks at things like the method, the headers and their order, and the accept-language value.

One point worth making plainly: JA4 is a way to summarise a handshake that a server is already seeing. A site computes it per connection and may compare it with whatever reference data it keeps. Neither JustBrowser nor ClickzProtect ships a JA4 signature database; JA4 is computed per visitor, never matched against a library we maintain. Public databases of JA4 values exist from third parties if you want to look at real-world populations.

Why a proxy does not change it

Your TLS fingerprint comes from your browser, not your IP address. A normal proxy forwards the handshake to the destination server unchanged. The proxy affects which IP the server sees, which is why, for geo testing, the proxy's location should agree with the profile's timezone and language, but it has no effect on the cipher suites and extensions your client offers. A setup that terminates TLS at the proxy and starts a second handshake is possible, but it breaks end-to-end certificate validation and brings signals of its own.

So the network layer is a property of the client software itself.

Why consistency across layers matters

A server can compare layers. The user agent string, the client hints headers, the JavaScript-visible navigator values and the TLS handshake all describe a client. When they do not, for example a user agent that names one browser family over a handshake that belongs to another, the disagreement is visible before the page even loads. Site owners use exactly this kind of cross-check to spot scripted clients that claim to be a browser they are not.

This is why the rest of this post is about consistency rather than tricks. Two situations show why it matters:

  • QA and testing. If you test your site's behaviour for different browsers, a test client that presents a mixed identity gives you results that do not match what real visitors experience. Use real browsers for each identity you test; for scripted runs, our Playwright and Puppeteer guide shows how to drive profiles over the local API.
  • Privacy and separation. If you keep separate profiles for different clients or storefronts, each profile should describe one coherent browser, with the same story at every layer.

It also explains why extensions and JavaScript-level tools cannot be the whole answer. They work inside the page. The handshake is produced by the browser's network stack, below the layer they can reach.

What JustBrowser does at the TLS layer

JustBrowser is a multi-account browser for teams. It is built on a custom Chromium engine with native C++ integration, not an extension or a wrapper, and it is patched on every upstream Chromium release.

At the TLS layer the stack is stock BoringSSL. Every JustBrowser profile sends the genuine Client Hello of the Chromium core it is built on, with GREASE values and all. That is the property that keeps the network layer honest: nothing is faked on the wire, so the handshake is simply what a Chromium browser sends.

Two consequences follow:

  • There is no emulation of other browser families. Chrome profiles run JustBrowser's own Chromium and Firefox profiles run a real Firefox engine. Keep each profile's identity on the engine it runs, so the user agent, the JavaScript-visible values and the handshake describe the same browser.
  • The core tracks upstream but is not always the same major version as the Chrome on your machine. The handshake matches the core's Chromium, not necessarily the Chrome build you have installed.

Each profile still has its own cookies, storage, proxy and 40+ identity parameters, so accounts you are allowed to hold stay separate and teammates can share profiles.

How to look at your own TLS fingerprint

  1. Find your JA4 value. You need a test page that computes it on the server from the handshake it received; JavaScript-only test pages cannot show it, because the handshake is not visible to scripts. Third-party databases such as ja4db.com then let you look up which clients produce a given value.
  2. Read the first segment. It is readable: TLS version, number of ciphers, number of extensions and ALPN. It tells you what kind of client the server thinks it is talking to.
  3. Compare with the browser you expect. A Chromium-based client should produce a Chromium-shaped value. Exact hashes vary by release and platform, so treat any example you find as illustrative.
  4. Check the other layers agree. Look at the user agent, the client hints and the timezone and language alongside the handshake. If one layer describes a different browser from the rest, that is the setting to fix.
  5. Look at HTTP/2 behaviour too. JA4H and related fingerprints cover the HTTP layer, and browsers differ there as well.

Common misunderstandings

"A proxy changes my fingerprint." It changes your IP, not the handshake.

"Randomising the handshake improves privacy." A randomised handshake does not match any real browser population, so it makes a client more distinctive, not less. For privacy, an ordinary, current handshake is the better choice.

"A JavaScript-only test covers the whole identity." JavaScript tests cannot see the TLS layer. Check the network layer separately.

"An old browser version is harmless." An outdated browser misses security fixes, and its handshake becomes rarer as everyone else updates, which also makes it more distinctive. This is another reason to use a browser that tracks upstream Chromium.

Where this connects to the rest of our products

If you operate a site and want to understand how traffic looks at the network layer, ClickzProtect uses signals like these when it scores traffic for affiliates and traffic operators. If you want privacy-respecting analytics that do not add fingerprinting signals of their own, JustAnalytics covers that.

Frequently Asked Questions

What is JA4+ TLS fingerprinting?

JA4+ is a network-layer fingerprinting method that summarises a client's TLS handshake: cipher suites, extensions, ALPN protocols and signature algorithms. Unlike canvas or WebGL fingerprinting, which runs in JavaScript, it is computed before any page loads. It was designed as a more structured successor to JA3, which was too coarse and easy to disturb by reordering extensions.

Why does the TLS fingerprint matter for browser consistency?

A site can compare what the handshake says about the client with what the page's JavaScript says. If the user agent claims one browser family but the handshake belongs to another, the two layers disagree. For QA and privacy work, the practical lesson is to keep every layer describing the same browser.

Can a proxy change my TLS fingerprint?

No. Your TLS fingerprint originates from your browser, not your proxy. A normal proxy forwards your handshake to the destination server unchanged. A proxy that terminates and re-establishes TLS breaks end-to-end certificate validation and introduces signals of its own.

How does JustBrowser handle the TLS layer?

JustBrowser's Chrome profiles run its own custom Chromium engine with native C++ integration, not a wrapper. Its TLS stack is unmodified BoringSSL, so the JA4 a Chrome profile sends is the genuine handshake of that Chromium core. Firefox profiles run a real Firefox engine instead of imitating one. Keep each profile's identity on the engine it runs, so the network layer and the JavaScript layer describe the same browser.

JustBrowser's 7-day trial (card required, cancel inside the week for no charge) gives full access so you can see how a native engine behaves for your own use case.


Try JustBrowser

A multi-account browser for teams, built on a custom Chromium engine, not an extension. Real C++ engine patches at the canvas / WebGL / audio / font / screen layer, across 40+ identity parameters. Local REST API + CDP for Playwright, Puppeteer, Selenium. $9.99/month or $99.99/year. 7-day free trial, card required — cancel any time in the seven days and you are not charged. Unlimited profiles.

Get started → · How it differs from Multilogin / GoLogin / AdsPower

Ready to manage multiple accounts?

Seven days free, then $9.99/month — one plan, everything included.

We'd like to use Google Analytics, a Google service, to understand how our website is used. It sets two cookies in your browser and runs only if you click Accept. You can change your choice at any time with Cookie settings. Cookie Policy

Sign-in cookies and the cookie that remembers this choice are always on; the website needs them to work.

Google Analytics, a Google service, helps us understand how our website is used. It sets two cookies, _ga and _ga_TVZHQ99TZW. It is now onoff in this browser. If your browser sends a Global Privacy Control or Do Not Track signal, it stays off. Cookie Policy