It is tempting to draw the history of TLS fingerprinting as a single line: JA3, then JA4, with Cisco Mercury somewhere nearby. That version is tidy. It is also wrong.
Two strands of work developed around the same observation: a TLS ClientHello exposes enough information to say something useful about the software that created it. One strand concentrated on portable identifiers that could be logged and exchanged. The other concentrated on retaining protocol structure and combining it with evidence that could improve classification.
JA3 and JA4 belong mainly to the first strand. Cisco Mercury belongs mainly to the second. For the technical work that preceded JA3, see how TLS handshakes became fingerprints.
Before JA3
Passive fingerprinting predates TLS. Tools such as p0f identified operating-system characteristics from TCP/IP behaviour without sending probes to the target. Researchers later applied the same instinct to fields exposed during SSL and TLS negotiation.
In 2009, Ivan Ristić published an SSL handshake fingerprinting experiment that compared ClientHello messages from web clients. Marek Majkowski followed with a TLS fingerprinting patch for p0f in 2012. Lee Brotherston's FingerprinTLS later provided tools and a database for creating and matching TLS fingerprints.
Salesforce's JA3 project drew directly on that work. JA3 serialised five ordered ClientHello feature groups, removed GREASE values and calculated an MD5 digest. The result was compact enough to put in a log, share in threat intelligence or match in a rule. The archived JA3 repository documents both the format and its debt to FingerprinTLS.
JA3's compactness came with a cost. A digest does not explain why two clients differ. Ordered inputs also meant that harmless permutation could produce a different value. Most importantly, a matching digest did not prove that the traffic came from one application. Programs built on a shared TLS library could produce the same ClientHello.
The JA4 branch
FoxIO introduced JA4 in 2023 after Chrome began permuting TLS extension order. Peakhour saw the practical effect of that change in our Chrome extension-randomisation analysis: a representation that preserved extension order split one common browser family into a large number of values.
JA4 canonicalises selected ClientHello features before hashing them. Its a_b_c structure keeps a readable summary in the first section, a digest of sorted cipher identifiers in the second, and a digest derived from extensions and signature algorithms in the third. This makes the components useful independently. An analyst can group on part of a JA4 value without pretending every field is identical.
That is deliberate lossy compression. JA4 is useful because it throws away distinctions its designers judged unstable or unhelpful for this job. It is not a reversible rendering of the ClientHello, and its truncated SHA-256 sections do not provide a measure of semantic distance. The exact format is set out in the FoxIO JA4 technical specification.
JA4 is one method. JA4+ is the name used for a wider family that includes server, HTTP, TCP, SSH, certificate and other fingerprints. Those methods do not all share JA4's licence, which matters if the fingerprints will be built into a commercial service.
The Cisco research branch
Cisco's work took a different route. In 2016, Blake Anderson, Subharthi Paul and David McGrew studied how observable TLS features could help distinguish malware from enterprise traffic without decrypting it. Their paper, Deciphering Malware's Use of TLS, also dealt with an awkward issue that still matters: malware-sandbox data can bias a classifier.
Anderson and McGrew's 2017 operating-system fingerprinting research combined evidence from TCP/IP, TLS and HTTP across multiple sessions. The point was not to mint a universally portable hash. It was to ask whether several kinds of passive evidence, accumulated over time, reduced uncertainty about the endpoint.
The same multi-protocol approach appears in Cisco's Joy and Mercury projects. Mercury's Network Protocol Fingerprinting format represents selected protocol features as a tree of hexadecimal byte strings. The full form retains structure. Its naming can state the protocol and fingerprint rule version. An optional compact hash can be used where a fixed-length value is more practical. Cisco's current draft NPF specification defines fingerprints for TLS, QUIC, TCP, HTTP, SSH and other protocols.
Mercury also keeps fingerprint generation separate from process classification. That distinction is easy to miss.
A fingerprint and a label are different things
In Cisco's 2020 paper, Accurate TLS Fingerprinting Using Destination Context and Knowledge Bases, the authors found that common TLS fingerprints mapped to many processes. For the 100 most prevalent fingerprints in their May 2020 data, the median was 24.5 process names per fingerprint.
Their response was not a longer hash. They combined the fingerprint with destination address, port and server name, then used a weighted naïve Bayes classifier backed by a continually updated knowledge base.
That produces an inference, not a property embedded in the fingerprint string. The result depends on labelled observations, their age, the monitored environment and the destination evidence available for the connection. The open Mercury repository can generate fingerprints without possessing Cisco's production knowledge base.
This is the clearest difference between the two lineages:
- JA3 and JA4 define portable representations for selected TLS observations.
- Mercury NPF retains a richer, versioned representation that can be fed into a separate analysis system.
- Mercury's destination-context classifier is another layer again.
None of these layers proves who made a request.
Where the lineages meet
The projects respond to many of the same protocol changes. Both JA4 and recent Mercury formats sort selected TLS fields to reduce instability caused by permutation. Both deal explicitly with GREASE. Both recognise that operators need compact values for logs as well as enough detail to investigate differences.
They make different trade-offs. JA4 is convenient for grouping and interchange. Mercury's full NPF form is better suited to inspection and to analysis that benefits from retained structure. JA4's wider family adds fingerprints for other observations, while Mercury is also a packet metadata collector and protocol-analysis library. Comparing only the length of their hashes misses most of the design.
The lab article makes that concrete. In one ClientHello, three fingerprints, we run JA3, JA4 and Mercury against the same packet capture, record the exact tool versions and compare what each output preserves.