helloprint
The first complete TLS fingerprint analysis toolkit for Go. Analyze, compute, and compare client fingerprints from the server/gateway perspective.
Zero CGo. Zero external dependencies. Pure Go.
Features
- Full TLS parsing — ClientHello & ServerHello with all extensions
- JA3 + JA3S — Industry-standard MD5-based fingerprints
- JA4 + JA4S — Next-generation sorted, truncated-SHA256 fingerprints
- Fingerprint database — Built-in signatures for Chrome, Firefox, Safari, Edge, curl, Go, Python, and more
- UA consistency check — Detect when User-Agent claims don't match TLS fingerprints
- HTTP middleware — Drop-in
net.Listener wrapper for transparent fingerprint extraction
- Fingerprint echo server — Like tls.peet.ws but self-hosted
Install
go install github.com/Easonliuliang/helloprint/cmd/helloprint@latest
Or as a library:
go get github.com/Easonliuliang/helloprint
CLI Usage
# Parse a ClientHello binary file
helloprint parse clienthello.bin
# Calculate all hashes
helloprint hash clienthello.bin
# Check User-Agent vs TLS fingerprint consistency
helloprint check --ua "Mozilla/5.0 (Chrome)..." clienthello.bin
# Start fingerprint echo server (visit https://localhost:8443)
helloprint serve --addr :8443
# Browse the built-in fingerprint database
helloprint db list
helloprint db lookup --ja3 "cd08e31494f9531f560d64c695473da9"
helloprint db lookup --ja4 "t13d1516h2"
Library Usage
Parse a ClientHello
import "github.com/Easonliuliang/helloprint/parse"
ch, err := parse.ParseClientHelloFromRecord(rawBytes)
fmt.Println(ch.SNI) // "example.com"
fmt.Println(ch.CipherSuitesNoGREASE()) // [0x1301 0x1302 ...]
Compute Fingerprints
import "github.com/Easonliuliang/helloprint/hash"
fmt.Println(hash.JA3Hash(ch)) // "cd08e31494f9531f560d64c695473da9"
fmt.Println(hash.JA4(ch)) // "t13d1516h2_8daaf6152771_02713d6af862"
Check UA Consistency
import (
"github.com/Easonliuliang/helloprint/database"
"github.com/Easonliuliang/helloprint/match"
)
db := database.Default()
verdict := match.CheckConsistency(userAgent, ja3Hash, ja4, db)
fmt.Println(verdict.Level) // "consistent", "suspicious", "mismatch", or "unknown"
fmt.Println(verdict.Score) // 0.0 ~ 1.0
fmt.Println(verdict.Reasons) // ["exact match between UA and TLS fingerprint"]
HTTP Middleware
import "github.com/Easonliuliang/helloprint/middleware"
ln, _ := net.Listen("tcp", ":443")
fpListener := &middleware.FingerprintListener{
Listener: ln,
TLSConfig: tlsConfig,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ch := middleware.GetClientHello(r.Context())
if ch != nil {
fmt.Fprintf(w, "Your JA3: %s", hash.JA3Hash(ch))
}
})
http.Serve(fpListener, nil)
Use Cases
| Use Case |
How |
| Bot detection |
UA says Chrome, but JA3 is Python requests? → Mismatch |
| Security research |
Extract fingerprints from pcap files |
| Gateway integration |
Embed as middleware in your reverse proxy |
| Traffic classification |
Route traffic based on client fingerprint |
Supported Fingerprints
| Algorithm |
Status |
Source |
| JA3 |
✅ |
Salesforce |
| JA3S |
✅ |
Salesforce |
| JA4 |
✅ |
FoxIO |
| JA4S |
✅ |
FoxIO |
| JA4H |
🔜 Phase 2 |
HTTP request fingerprint |
| JA4X |
🔜 Phase 2 |
X.509 certificate fingerprint |
| HTTP/2 |
🔜 Phase 2 |
SETTINGS/window/pseudo-header fingerprint |
Why not existing libraries?
| Library |
Stars |
Limitation |
| dreadl0ck/ja3 |
~150 |
Requires gopacket/CGo, JA3 only |
| exaring/ja4plus |
~29 |
JA4 only, no JA3 |
| fingerproxy |
- |
Full reverse proxy, not an embeddable library |
| helloprint |
- |
JA3+JA4 suite, zero CGo, embeddable library + CLI |
License
MIT — see LICENSE
JA4+ algorithms are subject to FoxIO License 1.1 (open-source use permitted).