JA4+ network fingerprinting library for TLS, TCP, HTTP, SSH, X.509, and DHCP analysis
Project description
A Python library and CLI for JA4+ network fingerprinting. Implements all ten JA4+ methods for identifying and classifying network traffic based on TLS, TCP, HTTP, SSH, X.509, and DHCP characteristics. Supports QUIC, IPv4/IPv6, and multi-segment TCP reassembly.
JA4+ is a set of network fingerprinting standards created by FoxIO. This library is an independent Python implementation of the published specification. For the original spec, see the FoxIO JA4+ repository.
Supported Fingerprint Types
| Type | Protocol | Description |
|---|---|---|
| JA4 | TLS/QUIC | Client fingerprint from ClientHello messages |
| JA4S | TLS/QUIC | Server fingerprint from ServerHello messages |
| JA4H | HTTP | Client fingerprint from request headers and cookies |
| JA4T | TCP | Client OS fingerprint from SYN packets |
| JA4TS | TCP | Server fingerprint from SYN-ACK packets |
| JA4L | TCP/QUIC | Light distance and latency estimation |
| JA4X | X.509 | Certificate structure fingerprint from OID sequences |
| JA4SSH | SSH | Session type classification from traffic patterns |
| JA4D | DHCPv4 | DHCP client/server fingerprint (FoxIO PR #267/#270) |
| JA4D6 | DHCPv6 | DHCPv6 client/server fingerprint (FoxIO PR #267/#270) |
QUIC Initial packets (RFC 9001/9369) are automatically decrypted to extract TLS ClientHellos. IPv4 and IPv6 are both supported across all fingerprinters.
Installation
pip install ja4plus
For fingerprint identification (browsers, malware, C2 frameworks):
pip install ja4plus[lookup]
CLI
The ja4plus command is available after installation:
# Analyze a PCAP file
ja4plus analyze capture.pcap
# JSON output for SIEM ingestion
ja4plus --format json analyze capture.pcap
# Only specific fingerprint types
ja4plus --types ja4,ja4t analyze capture.pcap
# Live capture (requires root)
sudo ja4plus live eth0
# Fingerprint a certificate
ja4plus cert server.der
# Identify known fingerprints
ja4plus --lookup analyze capture.pcap
Output formats: --format table (default), json (JSONL), csv
Fingerprint Lookup
ja4plus includes a bundled database of known JA4+ fingerprints from FoxIO's ja4plus-mapping.csv. Identifies Chrome, Firefox, Safari, Python, Cobalt Strike, Sliver, IcedID, and more.
from ja4plus.ja4db import lookup
result = lookup("t13d1516h2_8daaf6152771_02713d6af862")
# {"application": "Chromium Browser", "type": "ja4", "notes": ""}
Python API
Quick Start
from scapy.all import rdpcap
from ja4plus import JA4Fingerprinter
packets = rdpcap("capture.pcap")
fp = JA4Fingerprinter()
for packet in packets:
result = fp.process_packet(packet)
if result:
print(f"JA4: {result}")
All Fingerprinters
from ja4plus import (
JA4Fingerprinter, # TLS Client
JA4SFingerprinter, # TLS Server
JA4HFingerprinter, # HTTP
JA4TFingerprinter, # TCP Client (SYN)
JA4TSFingerprinter, # TCP Server (SYN-ACK)
JA4LFingerprinter, # Latency
JA4XFingerprinter, # X.509 Certificate
JA4SSHFingerprinter, # SSH
JA4DFingerprinter, # DHCPv4
JA4D6Fingerprinter, # DHCPv6
)
All fingerprinters share a common interface:
| Method | Description |
|---|---|
process_packet(pkt) |
Process a packet, returns fingerprint string or None |
get_fingerprints() |
Returns list of all collected fingerprint dicts |
reset() |
Clears all collected state |
Function-Based API
For one-shot fingerprinting without maintaining state:
from ja4plus import generate_ja4, generate_ja4s, generate_ja4h
fingerprint = generate_ja4(packet)
Aggregating Processor
Run every fingerprinter on each packet and get a list of results:
from ja4plus import Processor
p = Processor()
for packet in packets:
for r in p.process_packet(packet):
print(r["type"], r["fingerprint"], r.get("raw"))
# Use get_shard_key to bucket packets per connection
shard_key = p.get_shard_key(packet)
# Cleanup state for a finished connection
p.cleanup_connection(src_ip, src_port, dst_ip, dst_port, "tcp")
JA4 and JA4S result dicts include the unhashed raw and
raw_original_order variants — useful for human-readable output and
fingerprint debugging.
X.509 Helpers
from ja4plus import compute_ja4x_from_pem, compute_ja4x_from_der
ja4x = compute_ja4x_from_pem(pem_bytes)
ja4x = compute_ja4x_from_der(der_bytes)
See docs/usage.md for detailed usage of each fingerprinter and docs/api_reference.md for the full API.
Fingerprint Formats
| Type | Format | Example |
|---|---|---|
| JA4 | {proto}{ver}{sni}{ciphers}{exts}{alpn}_{hash}_{hash} |
t13d1516h2_8daaf6152771_e5627efa2ab1 |
| JA4S | {proto}{ver}{exts}{alpn}_{cipher}_{hash} |
t130200_1301_a56c5b993250 |
| JA4H | {method}{ver}{cookie}{ref}{cnt}{lang}_{h}_{h}_{h} |
ge11cr0800_edb4461d7a83_... |
| JA4T | {window}_{options}_{mss}_{wscale} |
65535_2-4-8-1-3_1460_7 |
| JA4TS | {window}_{options}_{mss}_{wscale} |
14600_2-4-8-1-3_1460_0 |
| JA4L | JA4L-{C|S}={latency_us}_{ttl} |
JA4L-S=2500_56 |
| JA4X | {issuer}_{subject}_{extensions} |
a37f49ba31e2_a37f49ba31e2_dd4f1a0ef8b2 |
| JA4SSH | c{mode}s{mode}_c{pkts}s{pkts}_c{acks}s{acks} |
c36s36_c51s80_c69s0 |
| JA4D | {type}{size}{ip}{fqdn}_{options}_{request_list} |
disco0000in_61-55_1-3-6-42 |
| JA4D6 | {type}{size}{ip}{fqdn}_{options}_{request_list} |
solct0014nn_1-6-8-25_23-24 |
Spec Validation
ja4plus is validated against FoxIO's official test vectors:
python tests/download_test_vectors.py
pytest -m spec_validation -v
Development
git clone https://github.com/Crank-Git/ja4plus.git
cd ja4plus
pip install -e ".[dev]"
pytest tests/ -v
Requirements
- Python 3.8+
- scapy >= 2.4.0
- cryptography >= 42.0.0
License
This library is released under the BSD 3-Clause License.
The JA4+ fingerprinting specifications were created by FoxIO. JA4 (TLS Client) is open source under BSD-3-Clause per FoxIO. Other JA4+ methods (JA4S, JA4H, JA4T, JA4TS, JA4L, JA4X, JA4SSH) implement FoxIO's specifications under the FoxIO License 1.1, which is permissive for academic, internal business, and security research use.
See LICENSE for full details.
Acknowledgments
JA4+ was created by John Althouse at FoxIO. This library is an independent implementation of the published specification. For the original spec and reference implementation, see github.com/FoxIO-LLC/ja4.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ja4plus-0.6.0.tar.gz.
File metadata
- Download URL: ja4plus-0.6.0.tar.gz
- Upload date:
- Size: 8.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4305117e5901f27c17de4742e95b610eb0437f162a4858be832f4b2fc0dfc831
|
|
| MD5 |
42c226a40362711476625963986b51c8
|
|
| BLAKE2b-256 |
e2a05371bc019047f9cf5ea83157bb6ccd96bac47703854495052fe18733c506
|
Provenance
The following attestation bundles were made for ja4plus-0.6.0.tar.gz:
Publisher:
publish.yml on Crank-Git/ja4plus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ja4plus-0.6.0.tar.gz -
Subject digest:
4305117e5901f27c17de4742e95b610eb0437f162a4858be832f4b2fc0dfc831 - Sigstore transparency entry: 1481843275
- Sigstore integration time:
-
Permalink:
Crank-Git/ja4plus@5ab02527fefb6b7c64c999ae2170311953670d10 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/Crank-Git
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5ab02527fefb6b7c64c999ae2170311953670d10 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ja4plus-0.6.0-py3-none-any.whl.
File metadata
- Download URL: ja4plus-0.6.0-py3-none-any.whl
- Upload date:
- Size: 2.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6705731c9bcdcc5600ea362c47a17ec44895188cd82ecf9f86eb26fe406c4f04
|
|
| MD5 |
3195fbd1a119f102dfe7c0458f85add9
|
|
| BLAKE2b-256 |
686277c299608e3b5be3646d486101f98d1ac8b80ca7bc60a97d4b0086ec6f8e
|
Provenance
The following attestation bundles were made for ja4plus-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on Crank-Git/ja4plus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ja4plus-0.6.0-py3-none-any.whl -
Subject digest:
6705731c9bcdcc5600ea362c47a17ec44895188cd82ecf9f86eb26fe406c4f04 - Sigstore transparency entry: 1481843332
- Sigstore integration time:
-
Permalink:
Crank-Git/ja4plus@5ab02527fefb6b7c64c999ae2170311953670d10 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/Crank-Git
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5ab02527fefb6b7c64c999ae2170311953670d10 -
Trigger Event:
release
-
Statement type: