Fingerprinting

What is JA3?

JA3 is a TLS client fingerprinting method that reads five fields from the ClientHello, joins their decimal values into a single string and hashes it with MD5. The fields are TLS version, cipher suites, extensions, supported elliptic curves and EC point formats. The 32-character result groups clients by TLS library and configuration.

The JA3 string joins five fields with commas: the TLS version, then dash-separated lists of cipher suites, extension types, supported groups and EC point formats, written as decimal code points in the order the client sent them. GREASE values are stripped first. MD5 over that string produces the hash you see in logs. JA3S is the server-side counterpart, built from the ServerHello's version, chosen cipher and extensions. Salesforce engineers published both in 2017, and network monitors such as Zeek and Suricata can record them against the connection.

A JA3 hash identifies a TLS stack and its settings, never a person. Every install of the same browser build on the same platform shares one value, which is what makes blending in possible and what makes hash blocklists blunt instruments. The distinctive values belong to tooling: a default python-requests install, curl against system OpenSSL, Go's net/http, a Node HTTP client. Threat intelligence work originally paired JA3 with JA3S to recognise malware families by the handshake their implants negotiate.

Two limits pushed the field along. JA3 preserves list order, so once Chrome began shuffling its extension order the same browser started producing a different hash on every connection, which wrecked allowlists built on a single value. The output is also one opaque digest, so you cannot ask whether a client offered HTTP/2 in ALPN or supported TLS 1.3 without a lookup table that maps hashes back to inputs. JA4 answers both by sorting the lists and keeping part of the fingerprint readable.

JA3 stays widely deployed because it is cheap to compute and nearly everything already logs it. Treat it as one input rather than a verdict. The useful signal is agreement: a JA3 known to belong to Chrome on Android arriving with Chrome-on-Android headers, matching HTTP/2 settings and a mobile carrier ASN. Any one of those alone is thin evidence. A python-requests JA3 wearing a browser User-Agent, by contrast, is scored in a single rule.

Where you meet it

You meet JA3 in a Zeek ssl.log, a Suricata alert, or a WAF rule that bans one hash outright. From the automation side you meet it as a 403 that never reaches your parsing code. Pull your client's JA3 from an echo endpoint, compare it with a real browser's on the same machine, and decide whether to swap TLS stacks or stop claiming to be a browser in your headers.

Common questions

Is JA3 still used?

Yes. It is cheap, well supported in Zeek, Suricata and most CDNs, and still records useful groupings. Browser extension-order randomisation made single-hash allowlists unreliable, so newer detection stacks log JA4 as well and often keep both values on the same connection record.

Can two different programs have the same JA3?

Yes, and most do. Any two programs linking the same TLS library with the same options negotiate the same handshake, so a dozen OpenSSL-based tools can share one hash. JA3 tells you which stack and configuration produced a connection, not which application or which user.

Why does JA3 use MD5?

MD5 is used as a short, fast label for the joined field string, not as a security control. Nothing about JA3 depends on collision resistance. If you need the underlying values you have to keep the original string, since the hash alone cannot be reversed.

Related terms

JA4
JA4 is the TLS client fingerprint in the JA4+ family published by FoxIO, designed to replace JA3. Rather than one opaque MD5, it produces a partly readable string: a ten-character prefix describing transport, TLS version, SNI, cipher and extension counts and ALPN, followed by two truncated SHA-256 digests of the sorted cipher and extension lists.
TLS Fingerprint
A TLS fingerprint is an identifier derived from the ClientHello a client sends when it opens an HTTPS connection: the TLS version offered, the ordered cipher suite list, the extension list, supported elliptic curves and signature algorithms. JA3 and JA4 are the common encodings of it. Different HTTP clients and browsers produce visibly different values.
Browser Fingerprint
A browser fingerprint is an identifier derived from the properties your browser exposes - user agent, screen and window dimensions, timezone, language, installed fonts, canvas and WebGL rendering output, audio stack behaviour, hardware concurrency. Combined, these values are often unique enough to recognise the same browser across sessions and sites without any cookie.
Device Fingerprint
A device fingerprint is an identifier built from the hardware and software traits a device exposes: screen geometry, GPU and driver strings, CPU core count, memory, timezone, languages, installed fonts, audio and canvas rendering, and touch support. Hashed together, those values are stable enough to recognise a returning device across sessions without any cookie.
P0F
p0f is a passive OS fingerprinting tool that identifies the system behind a connection by watching traffic rather than probing it. It reads TCP SYN packets for initial TTL, window size, MSS, the order of TCP options and a set of quirk flags, then matches them against a signature database. It sends nothing to the host it identifies.
Canvas Fingerprint
Canvas fingerprinting draws hidden text and shapes into an HTML5 canvas, reads the pixels back with toDataURL or getImageData, and hashes them. The exact output varies with GPU, graphics driver, font rendering and anti-aliasing, so the hash stays stable for one device and browser build while differing between machines.
WebGL Fingerprint
A WebGL fingerprint is an identifier derived from how a browser's GPU and graphics driver render 3D content. Sites read the renderer and vendor strings the driver reports, then hash the pixels of a small scene drawn off-screen. Capability limits from the context add more. The result stays stable across sessions and changes only when the hardware or driver does.

Real 4G/5G mobile and residential IPs

PROXIES.SX runs carrier IPs in 100+ countries with HTTP and SOCKS5 on every endpoint. $4/GB down to $2.40/GB at volume, free endpoints and rotation, and your GB never expire.