courses

tshark: Wireshark’s dissection on the command line

Wireshark’s brain, tcpdump’s ergonomics

tcpdump gives you fast, low-overhead capture; Wireshark gives you deep protocol dissection. tshark is the bridge — Wireshark’s dissectors and display-filter language, but on the terminal and scriptable. That makes it the right tool when you want to extract fields, follow streams, compute statistics, or emit JSON/CSV for downstream processing without opening a GUI. This page covers capture vs. display filters, field extraction, output formats, stream following, statistics, TLS decryption, and the one-liners that turn a capture into data.

Introduction

tshark is the command-line version of Wireshark. Where tcpdump excels at fast, low-overhead capture with BPF filtering, tshark brings Wireshark’s deep protocol dissection to the terminal — parsing hundreds of protocols, extracting fields by name, and producing structured output suitable for scripting.

Both tools use libpcap for capture, so the capture side is equivalent. The difference is in what you can do with the packets after capture: tshark understands application-layer protocols, can follow streams, decrypt TLS (given keys), and output JSON or CSV for downstream processing.

Basic Usage

# Capture on default interface, print to terminal
tshark

# Capture on a specific interface
tshark -i eth0

# List available interfaces
tshark -D

# Capture to a file
tshark -i eth0 -w capture.pcap

# Read from a saved file
tshark -r capture.pcap

# Limit capture to N packets
tshark -i eth0 -c 100

# Capture for N seconds
tshark -i eth0 -a duration:30

Display Filters

tshark supports two distinct filter systems:

Display filters are far more expressive than BPF because they operate on fully decoded packets.

# Show only HTTP traffic
tshark -r capture.pcap -Y 'http'

# Show only DNS queries
tshark -r capture.pcap -Y 'dns.flags.response == 0'

# Show only DNS responses with NXDOMAIN
tshark -r capture.pcap -Y 'dns.flags.rcode == 3'

# Show only TLS ClientHello packets
tshark -r capture.pcap -Y 'tls.handshake.type == 1'

# Show HTTP requests with a specific User-Agent
tshark -r capture.pcap -Y 'http.user_agent contains "curl"'

# Show TCP connections that were reset
tshark -r capture.pcap -Y 'tcp.flags.reset == 1'

# Show ICMP echo requests
tshark -r capture.pcap -Y 'icmp.type == 8'

# Show packets larger than 1400 bytes
tshark -r capture.pcap -Y 'frame.len > 1400'

# Combine with and/or
tshark -r capture.pcap -Y 'ip.src == 10.0.0.1 and tcp.port == 443'

Capture Filters

# Capture only traffic to/from a host (BPF, same as tcpdump)
tshark -i eth0 -f 'host 10.0.0.1'

# Capture only port 80 and 443
tshark -i eth0 -f 'tcp port 80 or tcp port 443'

# Capture and immediately apply a display filter
tshark -i eth0 -f 'not port 22' -Y 'http'

Extracting Specific Fields

The -T fields mode prints only the fields you specify with -e. This is extremely useful for extracting data for scripting.

# Extract source IP, destination IP, and protocol
tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e ip.proto

# Extract DNS query names
tshark -r capture.pcap -Y 'dns' -T fields -e dns.qry.name

# Extract HTTP request URIs
tshark -r capture.pcap -Y 'http.request' -T fields -e http.request.method -e http.request.uri -e http.host

# Extract TLS SNI (Server Name Indication) — hostnames from encrypted traffic
tshark -r capture.pcap -Y 'tls.handshake.extensions_server_name' -T fields -e tls.handshake.extensions_server_name

# Add a header line and use tab separation
tshark -r capture.pcap -Y 'dns' -T fields -e frame.number -e ip.src -e dns.qry.name -E header=y -E separator=,

Field Output Options (-E)

Option Values Description
header=y/n y, n Print column header row
separator=, any char Field delimiter (default: tab)
quote=d/s/n d, s, n Quote fields with double, single, or no quotes
occurrence=f/l/a f, l, a For repeated fields: first, last, or all occurrences

Output Formats

# Default columnar output
tshark -r capture.pcap

# JSON output (one object per packet, fully decoded)
tshark -r capture.pcap -T json

# JSON with only selected fields
tshark -r capture.pcap -T jsonfields -e ip.src -e ip.dst

# PDML (XML, Packet Details Markup Language)
tshark -r capture.pcap -T pdml

# Plain text fields
tshark -r capture.pcap -T fields -e frame.number -e ip.src

# EK (Elasticsearch bulk import JSON)
tshark -r capture.pcap -T ek

Following Streams

# Follow a TCP stream (reassembles the full conversation)
tshark -r capture.pcap -z follow,tcp,ascii,0

# Follow stream number 3
tshark -r capture.pcap -z follow,tcp,ascii,3

# Follow a UDP stream
tshark -r capture.pcap -z follow,udp,ascii,0

# Follow HTTP stream
tshark -r capture.pcap -z follow,http,ascii,0

The stream index corresponds to Wireshark’s stream numbering. Use tcp.stream == N as a display filter to identify which stream you want first.

Statistics

tshark -z provides a wide range of built-in statistics.

# Protocol hierarchy — what protocols are present and how much traffic each carries
tshark -r capture.pcap -z io,phs -q

# Conversation list (all IP pairs that communicated)
tshark -r capture.pcap -z conv,ip -q

# TCP conversation list
tshark -r capture.pcap -z conv,tcp -q

# Endpoint list (all IPs seen)
tshark -r capture.pcap -z endpoints,ip -q

# HTTP request/response statistics
tshark -r capture.pcap -z http,tree -q

# DNS statistics
tshark -r capture.pcap -z dns,tree -q

# IO statistics (packet counts per time interval)
tshark -r capture.pcap -z io,stat,1 -q

# Expert info (warnings, errors, notes from dissectors)
tshark -r capture.pcap -z expert -q

The -q flag suppresses per-packet output so only the statistics are shown.

TLS Decryption

If you have the session keys (via SSLKEYLOGFILE), tshark can decrypt TLS traffic.

# Capture while logging TLS keys from your browser or application
export SSLKEYLOGFILE=~/tls-keys.log
chromium &
tshark -i eth0 -w capture.pcap

# Decrypt during analysis
tshark -r capture.pcap -o tls.keylog_file:tls-keys.log -Y 'http'

# Extract decrypted HTTP URIs
tshark -r capture.pcap -o tls.keylog_file:tls-keys.log -Y 'http.request' \
    -T fields -e http.request.uri

Many runtimes support SSLKEYLOGFILE: Chrome, Firefox, curl, Python’s ssl module (via a wrapper), and OpenSSL applications built with the right hooks.

Useful One-Liners

# Top talkers — count packets per source IP
tshark -r capture.pcap -T fields -e ip.src | sort | uniq -c | sort -rn | head

# All unique DNS names queried
tshark -r capture.pcap -Y 'dns.flags.response == 0' -T fields -e dns.qry.name | sort -u

# All HTTP hosts contacted
tshark -r capture.pcap -Y 'http.request' -T fields -e http.host | sort -u

# All TLS SNI names (encrypted traffic destinations)
tshark -r capture.pcap -Y 'tls.handshake.type == 1' -T fields -e tls.handshake.extensions_server_name | sort -u

# Extract HTTP response codes and URIs
tshark -r capture.pcap -Y 'http.response' -T fields -e http.request.uri -e http.response.code

# Find all files transferred over HTTP (Content-Disposition or content-type)
tshark -r capture.pcap -Y 'http' -T fields -e http.content_type -e http.file_data

# Count packets by protocol
tshark -r capture.pcap -T fields -e frame.protocols | sort | uniq -c | sort -rn

Comparing tshark and tcpdump

Feature tcpdump tshark
Protocol dissection Basic (IP/TCP/UDP headers) Deep (hundreds of protocols)
Filter syntax BPF only BPF (capture) + display filters
Field extraction No Yes (-T fields -e)
Stream reassembly No Yes (-z follow)
JSON/structured output No Yes (-T json, -T ek)
TLS decryption No Yes (with key log)
Overhead Very low Higher (full decode)
Availability Ubiquitous Requires Wireshark install

Use tcpdump when you need fast, lightweight capture — especially on embedded systems or servers without Wireshark installed. Use tshark when you need protocol-aware filtering, field extraction, or stream reassembly.

Key takeaways

References


Related course pages: Capturing traffic with tcpdump · Analyzing traffic with Wireshark · Network flow analysis

🛠️ Maintenance note: tshark output formats and -z statistic names evolve between Wireshark major releases (the -T ek/jsonfields modes especially), and display-filter field names occasionally change — the linked display filter reference is authoritative. Re-verify the TLS-keylog decryption flow each term, since browser/runtime support for SSLKEYLOGFILE shifts.