Tshark (Terminal-based Wireshark) is the command-line counterpart to Wireshark. It shares the exact same core packet-capture and dissection engine as Wireshark — the same protocol dissectors, the same filter language, the same capture library (libpcap/Npcap) — but exposes it entirely through a text-based interface instead of a GUI. This makes Tshark the tool of choice whenever packet analysis needs to happen without a graphical environment: on headless servers, over SSH sessions, inside automated pipelines, in CI/CD security testing, or on resource-constrained systems.
Because Tshark understands the identical capture filter (BPF) and display filter syntax as Wireshark, analysts can prototype filters visually in Wireshark and then port them directly to Tshark for scripted, repeatable, high-volume processing. Tshark can output data as plain text, fields in CSV, JSON, PDML/PSML XML, and more, making it easy to feed into other tools such as grep, awk, jq, Python scripts, or SIEM ingestion pipelines.
In Kali Linux, Tshark is installed as part of the wireshark / tshark packages and is heavily used in scripted penetration testing and network forensics workflows where a GUI is impractical.
How to Install
# Update package lists
sudo apt update
# Install tshark (also installs as part of the wireshark package group)
sudo apt install tshark -y
# During install you may again be prompted:
# "Should non-superusers be able to capture packets?" -> select <Yes>
Allow a non-root user to capture (same group mechanism as Wireshark):
sudo usermod -aG wireshark $USER
newgrp wireshark
Verify installation:
tshark --version
Expected output:
TShark (Wireshark) 4.2.5 (Git commit unknown)
Copyright 1998-2024 Gerald Combs <gerald@wireshark.org> and contributors.
License GPLv2+: GNU GPL version 2 or later
...
Compiled with libpcap, with POSIX capabilities, with libnl 3, with GLib 2.78.4
Running on Linux 6.6.15-amd64, with libpcap version 1.10.4
Syntax
tshark [OPTIONS] ...
General patterns:
tshark -i eth0 # Live capture, printed to terminal
tshark -i eth0 -w out.pcapng # Live capture, saved to a file
tshark -r in.pcapng # Read from an existing capture
tshark -r in.pcapng -Y "http.request" # Read + display filter
tshark -r in.pcapng -T fields -e ip.src -e ip.dst # Field extraction
All Command-Line Options (Kali Linux)
-h, --help Print help and exit
-v, --version Print version and exit
Capture:
-i <interface> Name/index/pipe of interface (or 'any')
-f <capture filter> BPF capture filter
-s <snaplen> Snapshot length
-p Don't use promiscuous mode
-I Capture in monitor mode
-B <buffer size> Capture buffer size (MB)
-y <link type> Link layer type
-D Print interfaces list and exit
-L Print link-layer types for interface and exit
--list-time-stamp-types List time stamp types for interface
Stop conditions:
-c <packet count> Stop after n packets
-a <autostop cond.> duration:NUM, filesize:NUM, files:NUM, packets:NUM
Output/ring buffer:
-b <ringbuffer opt.> duration:NUM, filesize:NUM, files:NUM
-w <outfile|-> Write raw packet data to outfile
Input file:
-r <infile> Read packets from infile
Processing:
-Y <display filter> Apply display filter (post-capture)
-R <read filter> Read filter (only with -2, two-pass mode)
-n Disable name resolution
-N <mtnNdsv> Enable specific name resolution
-d <selector>==<value>,<proto> Decode as
-2 Two-pass analysis
Output format:
-T pdml|ps|psml|text|fields|json|jsonraw|ek Output format
-e <field> Field to display (used with -T fields)
-E <field option> Field output options (header=y, separator=, quote=, etc.)
-x Add hex/ASCII dump to output
-V Add packet detail (verbose) view
-O <protocols> Only show packet details for listed protocols
-S <separator> Line separator for output records
-t a|ad|d|dd|e|r|u|ud Timestamp format
-u s|hms Seconds format
Statistics:
-z <statistics> Show statistics (e.g., io,phs / conv,tcp / http,tree)
-q Combined with capture, don't print packets
-Q Quit after capture (no display)
Miscellaneous:
-K <keytab> Kerberos keytab
-o <preference>:<value> Set a preference
-C <config profile> Use configuration profile
-G [report] Dump internal Wireshark data (fields, protocols, etc.)
5. Basic Usage (Expected Output in Bash)
List interfaces:
tshark -D
Output:
1. eth0
2. wlan0
3. lo (Loopback)
4. any
5. bluetooth0
Basic live capture (Ctrl+C to stop):
tshark -i eth0
Output:
Capturing on 'eth0'
1 0.000000 192.168.1.10 → 8.8.8.8 DNS 74 Standard query 0x1a2b A example.com
2 0.021345 8.8.8.8 → 192.168.1.10 DNS 90 Standard query response 0x1a2b A 93.184.216.34
3 0.023110 192.168.1.10 → 93.184.216.34 TCP 74 51322 → 443 [SYN] Seq=0 Win=64240 Len=0
4 0.045992 93.184.216.34 → 192.168.1.10 TCP 74 443 → 51322 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0
^C4 packets captured
Practical Examples with Output
Example 1: Capture 20 packets and write to a file
tshark -i eth0 -c 20 -w capture.pcapng
Output:
Capturing on 'eth0'
20 packets captured
Example 2: Read a file and filter for HTTP requests
tshark -r capture.pcapng -Y "http.request"
Output:
45 3.120044 192.168.1.10 → 93.184.216.34 HTTP 421 G ET /index.html HTTP/1.1
88 5.882221 192.168.1.10 → 151.101.1.69 HTTP 389 G ET /style.css HTTP/1.1
Example 3: Extract specific fields to CSV format
tshark -r capture.pcapng -T fields -e frame.number -e ip.src -e ip.dst -e tcp.port -E header=y -E separator=, > flows.csv
Output (flows.csv, first lines):
frame.number,ip.src,ip.dst,tcp.port
1,192.168.1.10,8.8.8.8,
3,192.168.1.10,93.184.216.34,51322
4,93.184.216.34,192.168.1.10,443
Example 4: JSON output for scripted parsing
tshark -r capture.pcapng -Y "dns" -T json > dns.json
Output (dns.json excerpt):
[
{
"_index": "packets-2026-07-19",
"_source": {
"layers": {
"frame": { "frame.number": "1" },
"dns": {
"dns.qry.name": "example.com",
"dns.qry.type": "1"
}
}
}
}
]
Example 5: Protocol hierarchy statistics
tshark -r capture.pcapng -q -z io,phs
Output:
===================================================================
Protocol Hierarchy Statistics
Filter:
eth frames:15234 bytes:12432011
ip frames:15036 bytes:12213984
tcp frames:11607 bytes:9812443
http frames:1843 bytes:1921012
udp frames:3429 bytes:2301102
dns frames:2880 bytes:1103221
===================================================================
Example 6: TCP conversation statistics
tshark -r capture.pcapng -q -z conv,tcp
Output:
================================================================================
TCP Conversations
Filter:<No Filter>
| <- | | -> | | Total |
A B Frames Bytes Frames Bytes Frames Bytes Duration
192.168.1.10:51322 93.184.216.34:443 420 310120 422 302011 842 612131 14.221
================================================================================
Example 7: Extract all unique DNS query names
tshark -r capture.pcapng -Y "dns.flags.response==0" -T fields -e dns.qry.name | sort -u
Output:
example.com
google.com
kali.org
pypi.org
Example 8: Live capture with rotating output files (ring buffer)
tshark -i eth0 -b filesize:10240 -b files:5 -w /var/captures/cap.pcapng
Output:
Capturing on 'eth0'
(writes cap.pcapng, cap.pcapng_00001_..., ... rotating after every 10MB,
keeping a maximum of 5 files)
Example 9: Follow a TCP stream from the command line
tshark -r capture.pcapng -q -z follow,tcp,ascii,0
Output:
===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 0
Node 0: 192.168.1.10:51322
Node 1: 93.184.216.34:443
===================================================================
Example 10: Filter and count packets matching a BPF capture filter live
tshark -i eth0 -f "icmp" -c 5
Output:
Capturing on 'eth0'
1 0.000000 192.168.1.10 → 8.8.8.8 ICMP 98 Echo (ping) request id=0x1 seq=1/256
2 0.020112 8.8.8.8 → 192.168.1.10 ICMP 98 Echo (ping) reply id=0x1 seq=1/256
3 1.001233 192.168.1.10 → 8.8.8.8 ICMP 98 Echo (ping) request id=0x1 seq=2/512
4 1.021002 8.8.8.8 → 192.168.1.10 ICMP 98 Echo (ping) reply id=0x1 seq=2/512
5 2.002344 192.168.1.10 → 8.8.8.8 ICMP 98 Echo (ping) request id=0x1 seq=3/768
5 packets captured
Example 11: HTTP request/response statistics tree
tshark -r capture.pcapng -q -z http,tree
Output:
================================================================================
HTTP/Requests
Topic / Item Count Average Min val Max val Rate (ms) Percent
HTTP 120 100%
G ET 95 79.17%
POST 25 20.83%
Status Code:200 88 73.33%
Status Code:404 12 10.00%
================================================================================
Example 12: Extract credentials from unencrypted FTP traffic
tshark -r ftp_capture.pcapng -Y "ftp.request.command==USER or ftp.request.command==PASS" -T fields -e ftp.request.command -e ftp.request.arg
Output:
USER admin
PASS Sup3rSecret!
Common Use Cases
- Automated, scheduled packet captures on servers with no GUI (e.g., via cron).
- Fast field extraction for feeding SIEMs, log pipelines, or custom Python/Bash analysis scripts.
- CI/CD pipeline network testing — verifying that specific protocol handshakes occur as expected.
- Remote packet analysis over SSH where forwarding a GUI is impractical.
- Bulk statistics generation across many capture files for reporting.
- Extracting IOCs (indicators of compromise) such as suspicious DNS queries or destination IPs from large pcap archives.
- Lightweight, resource-constrained capture on embedded devices or cloud VMs.
Automation with Bash
Continuous capture with automatic daily rotation and filtering for suspicious DNS traffic:
#!/bin/bash
# dns_monitor.sh - captures traffic, extracts DNS queries hourly
IFACE="eth0"
OUTDIR="/var/log/tshark"
mkdir -p "$OUTDIR"
while true; do
TS=$(date +%Y%m%d_%H%M%S)
OUTFILE="${OUTDIR}/dns_${TS}.pcapng"
tshark -i "$IFACE" -f "udp port 53" -a duration:3600 -w "$OUTFILE"
tshark -r "$OUTFILE" -Y "dns.flags.response==0" -T fields -e frame.time -e ip.src -e dns.qry.name \
>> "${OUTDIR}/dns_queries.log"
done
Batch-processing many pcap files to extract a summary CSV report:
#!/bin/bash
# summarize_pcaps.sh
echo "file,packets,tcp_packets,udp_packets,dns_queries" > summary.csv
for f in /data/pcaps/*.pcap; do
total=$(tshark -r "$f" -q -z io,stat,0 2>/dev/null | grep -c "^|")
tcp=$(tshark -r "$f" -Y "tcp" -T fields -e frame.number | wc -l)
udp=$(tshark -r "$f" -Y "udp" -T fields -e frame.number | wc -l)
dns=$(tshark -r "$f" -Y "dns.flags.response==0" -T fields -e frame.number | wc -l)
echo "$f,$total,$tcp,$udp,$dns" >> summary.csv
done
echo "[*] Report written to summary.csv"
Piping live extracted fields directly into another tool (e.g., real-time alerting on suspicious ports):
tshark -i eth0 -f "tcp" -T fields -e ip.src -e tcp.dstport 2>/dev/null | \
while read -r src port; do
if [[ "$port" == "4444" || "$port" == "1337" ]]; then
echo "[ALERT] Suspicious connection from $src to port $port at $(date)"
fi
done
Tips and Best Practices
- Use
-Qcombined with-zstatistics for lean, script-friendly summary output without printing every packet. - Prefer -T fields -e … over parsing
-T textoutput with regex; field extraction is far more reliable for automation. - Use
-2(two-pass analysis) when applying read filters (-R) that depend on later packets, such as TCP reassembly-dependent filters. - Always apply capture filters (
-f, BPF syntax) rather than display filters (-Y) when you can, since capture filters reduce the data volume at the point of capture and improve performance. - When writing automation, always redirect
stderr(2>/dev/null) to avoid polluting parsed output with warnings. - Combine Tshark with
jqfor powerful JSON-based filtering: tshark -r file.pcap -T json | jq ‘.[]._source.layers.dns’. - Use ring buffers (
-b) for long-running captures to avoid filling disk space. - Keep dissectors updated; run sudo apt upgrade tshark wireshark-common regularly since protocol dissection accuracy depends on dissector freshness.
Troubleshooting
Problem: “You don’t have permission to capture on that device.” Solution: Same fix as Wireshark — add user to wireshark group, ensure dumpcap has proper capabilities via setcap.
Problem: Tshark hangs with no output during a live capture. Solution: Confirm traffic is actually reaching the interface (ip -s link show eth0); check that a capture filter isn’t inadvertently excluding all traffic; try without -f first.
Problem: JSON/PDML output is too large / slow for very big captures. Solution: Apply a display filter before exporting, or extract only needed fields with -T fields -e instead of full -T json/-T pdml.
Problem: -z statistics show no output. Solution: Statistics with -z require -q in live-capture mode (otherwise packet-by-packet printing interferes); with -r file mode, ensure the requested -z name is spelled correctly (tshark -z help lists them).
Problem: Ring buffer files not rotating as expected. Solution: Ensure -w is used together with -b; ring buffer options only apply when writing raw capture files, not when using -T text output modes.
Problem: Slow performance during large-file field extraction. Solution: Avoid -x (hex dump) and -V (verbose) unless needed; they add significant processing overhead. Use targeted -Y filters to shrink the working set first.
References
- Tshark man page: https://www.wireshark.org/docs/man-pages/tshark.html
- Wireshark Display Filter Reference: https://www.wireshark.org/docs/dfref/
- Wireshark User’s Guide (CLI chapter): https://www.wireshark.org/docs/wsug_html_chunked/AppToolstshark.html
- Kali Linux Tools listing for Tshark: https://www.kali.org/tools/wireshark/
- Wireshark Wiki (Statistics, -z options): https://wiki.wireshark.org/Statistics