ja4plus — command-line output formats

Feature set structured-output · three formats, two contracts.

Table no stability promise

For a person reading a terminal. Columns may change between releases.

ja4plus analyze capture.pcap Source Type Fingerprint ------------------------------------------------------------------------------------------ 192.168.1.10:54321 -> 93.184.216.34:443 ja4 t13d1516h2_8daaf6152771_02713d6af862 192.168.1.10:54321 -> 93.184.216.34:443 ja4t 64240_2-1-3-1-1-4_1460_8 93.184.216.34:443 -> 192.168.1.10:54321 ja4s t130200_1301_234ea6891581 93.184.216.34:443 -> 192.168.1.10:54321 ja4x 2bab15409345_af684594efb4_000000000000 192.168.1.22:41002 -> 10.0.0.5:22 ja4ssh c36s36_c76s124_c0s0 [ja4plus] 4812 packets, 5 fingerprints, 3 connections

JSON Lines schema_version 1

One object per line. Every field is always present; an absent value is null.

ja4plus analyze capture.pcap --format json {"schema_version":1,"timestamp":"2026-08-06T12:34:56.789012Z","type":"ja4","fingerprint":"t13d1516h2_8daaf6152771_02713d6af862","raw":"t13d1516h2_002f,0035,...","raw_original_order":"t13d1516h2_1301,1303,...","src_ip":"192.168.1.10","src_port":54321,"dst_ip":"93.184.216.34","dst_port":443,"identified_as":null} {"schema_version":1,"timestamp":"2026-08-06T12:34:56.789012Z","type":"ja4t","fingerprint":"64240_2-1-3-1-1-4_1460_8","raw":null,"raw_original_order":null,"src_ip":"192.168.1.10","src_port":54321,"dst_ip":"93.184.216.34","dst_port":443,"identified_as":null}

With --lookup, only identified_as changes. No field appears or disappears.

ja4plus analyze capture.pcap --format json --lookup | jq -c '{type,fingerprint,identified_as}' {"type":"ja4","fingerprint":"t13d1516h2_8daaf6152771_02713d6af862","identified_as":"Chromium Browser"} {"type":"ja4t","fingerprint":"64240_2-1-3-1-1-4_1460_8","identified_as":null}

CSV schema_version 1

Fixed column order. The header is identical whatever flags the user passed.

ja4plus analyze capture.pcap --format csv schema_version,timestamp,type,fingerprint,raw,raw_original_order,src_ip,src_port,dst_ip,dst_port,identified_as 1,2026-08-06T12:34:56.789012Z,ja4,t13d1516h2_8daaf6152771_02713d6af862,"t13d1516h2_002f,0035,...","t13d1516h2_1301,1303,...",192.168.1.10,54321,93.184.216.34,443, 1,2026-08-06T12:34:56.789012Z,ja4t,64240_2-1-3-1-1-4_1460_8,,,192.168.1.10,54321,93.184.216.34,443,

Diagnostics

Results go to standard output. Everything else goes to standard error, so a pipe stays clean.

ja4plus analyze broken.pcap --format json > out.jsonl [ja4plus] warning: ja4x failed on packet 812: certificate length exceeds packet [ja4plus] 1 fingerprinter error, 4811 packets read ja4plus analyze capture.pcap --output out.jsonl Error: out.jsonl already exists. Pass --force to overwrite.

Field reference

FieldTypeMeaning
schema_versionintegerRises when a field is removed or its meaning changes.
timestampstring or nullThe packet timestamp, in RFC 3339 form.
typestringThe method name, lowercase.
fingerprintstringThe fingerprint. Never empty.
rawstring or nullThe unhashed form, when the method defines one.
raw_original_orderstring or nullThe unhashed wire-order form.
src_ip, dst_ipstringAddresses. Empty when the packet carries none.
src_port, dst_portintegerPorts. Zero when the packet carries none.
identified_asstring or nullThe application name from the mapping file. Null without --lookup.

This mockup is guidance, not a contract. It shows the intent of the output formats and roughly what a user sees. An implementer may diverge where the feature's requirements and acceptance criteria are still met. The one part that is a contract is the CSV column order and the JSON field set, and those live in features/05-structured-output.md.