# PCAP Viewer

> Open .pcap and .pcapng captures in your browser: packet list, protocol dissection tree and hex highlighting. The capture file is never uploaded.

- URL: https://bytescope.dev/en/pcap-viewer/
- Locale: en · Also: [ja](https://bytescope.dev/ja/pcap-viewer.md) · [zh-Hant](https://bytescope.dev/zh-Hant/pcap-viewer.md)
- Runs: Your files never leave your browser — all processing is local.
- Requires: Any modern browser (Chrome, Edge, Firefox, Safari), desktop and mobile.
- Updated: 2026-09-08

## What it does

Drop a `.pcap` or `.pcapng` file here and you get the three panes a packet analyst actually works in: a virtual-scrolling packet list with No. / Time / Source / Destination / Protocol / Length / Info, a dissection tree for the selected frame, and a hex/ASCII pane wired to the tree in both directions. Click a field and exactly its bytes light up; click a byte and the innermost field covering it is revealed and selected. A field that lives inside a byte — a TCP flag, an IP fragment bit — highlights the byte it sits in *and* draws the bit positions, because the byte on its own is not the answer.

Not uploading is the point of this tool, not a feature of it. A capture file is a map of the network it came from: internal addressing, hostnames in DNS queries and TLS SNI, certificate subjects, user agents, sometimes credentials in cleartext protocols. Every competing web viewer asks you to post that to their server. Here the file is read by the tab, handed to a Web Worker, and dissected in memory — there is no upload endpoint, and you can confirm it in DevTools: opening a capture produces no network request at all.

The container layer reads classic libpcap in all four magic numbers (little- and big-endian, microsecond and nanosecond) and pcapng with multiple interface blocks, enhanced and simple packet blocks, comments and name-resolution blocks. The summary card reports the format, byte order, version, every interface with its link type and snaplen, packet count, capture time range and any parse warning the container produced, with the frame number that caused it. A truncated or damaged file is not fatal: the packets that were read are shown, and the damage is reported as a warning instead of an error page.

Dissection covers Ethernet, 802.1Q and QinQ VLAN, Linux SLL and SLL2, raw IP and Null/Loopback at the link layer; ARP, IPv4 with options and fragment reassembly, IPv6 with extension headers, ICMPv4, ICMPv6 including NDP, TCP with full flags, options and sequence analysis, and UDP; then DNS, HTTP/1 with chunked bodies and cross-segment reassembly, TLS records and handshakes, cleartext HTTP/2 with HPACK, and QUIC. What is *not* decoded is stated on the page rather than hidden in a footnote — see the honesty panel above the tree.

## Limits

Does not capture live traffic from the browser and does not decrypt TLS; it parses .pcap/.pcapng files you already have.

## Machine output

Copy JSON copies an envelope `{ tool, url, generatedAt, userAgentHint, result }`. `tool` is `"pcap-viewer"`; `result` is the on-screen capture summary and packet-list columns below. The dropped file name, packet payload bytes, hex dumps, and follow-stream bodies are omitted. DNS names and TCP flags appear only as they do in the Info column.

- `format` (string | null) — `"pcap"` | `"pcapng"`. `null` = not supplied.
- `byteOrder` (string | null) — `"LE"` | `"BE"`. `null` = not supplied.
- `version` (object | null) — Container version `{ major, minor }`. `null` = not supplied.
- `packetCount` (number | null) — Packets the container declared. `null` = not supplied.
- `byteLength` (number | null) — Capture size in bytes. `null` = not supplied.
- `firstTimestampNs` (string | null) — First packet time as a decimal nanosecond string. `null` = not present on the summary.
- `lastTimestampNs` (string | null) — Last packet time as a decimal nanosecond string. `null` = not present on the summary.
- `gunzipped` (boolean) — The file was gunzipped before parsing.
- `shb` (object | null) — Section header hardware / os / userAppl (each string or `null`). `null` = no SHB option block on screen.
- `interfaces` (object) — Capture interfaces as shown (id, linkType, linkTypeName, snapLen, name or `null`), capped at 200. `totalCount` is the real interface count.
- `comments` (object) — SHB/EPB comments in file order, capped at 200.
- `decryptionSecrets` (object | null) — DSB presence as shown: `count` and `types` only — never key material. `null` = no secrets block.
- `warnings` (object) — Parse warnings in parse order, capped at 200. Each: `frame` (0 = container), `message`.
- `packets` (object) — Packet-list rows in file order, capped at 200. Each: `number`, `timestampNs` (decimal string), `originalLength`, `capturedLength`, `streamId` (or `null`), `protocol` (or `null` if the cell was empty; `"raw"` = not dissected; `"data"` = unknown application payload), `source`, `destination`, `info`. `totalCount` is `max(container packetCount, supplied length)`, not the copied length. Payload bytes are omitted.
- `protocolCounts` (object) — Packet and on-wire byte counts per protocol, counted over every supplied packet (not the copied prefix), sorted by packets descending then protocol. Capped at 200.
- `talkers` (object) — Packet and on-wire byte counts per source/destination address, counted over every supplied packet, sorted by packets descending then address. Capped at 200. `totalCount` is the real distinct-address count.

## FAQ

### Is my capture uploaded anywhere?

No. The file is read with the FileReader API, transferred to a Web Worker inside the same tab, and dissected there. This page makes no network request while you use it, so you can leave DevTools open on the Network tab and watch it stay empty. That matters more here than on most tools: a capture contains your internal topology, your hostnames and often your certificates, and handing that to a stranger's server to read two packets is a bad trade.

### How large a capture can it open?

256 MiB. The whole file has to sit in the tab's memory to be dissected, and past that a browser tab tends to be killed rather than finish, so the tool refuses the file and says so instead of freezing. Split a bigger capture first — `editcap -c 200000 big.pcap part.pcap` cuts it into 200,000-packet pieces, and `tcpdump -r big.pcap -w small.pcap -c 100000` takes the first 100,000. Gzipped captures (`.pcap.gz`) are decompressed in the tab, and the same ceiling applies to the decompressed size.

### Can it decrypt TLS or HTTPS?

No, and it does not pretend to. Without the session keys, TLS application data is ciphertext and stays ciphertext. What is in the clear is shown in full: the record layer, the handshake, the SNI, the ALPN list, the offered and negotiated versions and cipher suites, and the certificate's subject, issuer, validity and SANs. HTTP/2 is only readable in cleartext (h2c or prior knowledge); over TLS it is not. For QUIC, only Initial packets decode — their keys are derived from public values in RFC 9001 — so the page can tell you a flow is HTTP/3 and show the ClientHello's SNI and ALPN, and nothing beyond that.

### A pcapng file can carry TLS keys. Does it use them?

It reports them and does not use them. pcapng has a Decryption Secrets Block, and a capture written by a browser with `SSLKEYLOGFILE` set can carry the session keys inside the file itself — Wireshark will decrypt it. This tool reads the block, tells you how many secrets and of what type the file contains, and decrypts nothing. Saying "encrypted" while quietly holding the keys, or staying silent about keys the file plainly contains, would both be dishonest; reporting them and stopping is the honest position for v1.

### My capture opens but the tree is empty. Why?

Almost certainly a link layer this version does not dissect. v1 handles Ethernet, 802.1Q/QinQ, Linux SLL and SLL2, raw IP and Null/Loopback. Frame Relay, Token Ring, FDDI, 802.11 with radiotap and the various serial encapsulations exist in the wild, and such a file opens here — the container, the packet list, the timestamps and the raw bytes are all real — but dissection stops at the frame. The page names the link type and says so on screen, because an empty tree with no explanation is the dishonest failure mode.

### Does it replace Wireshark?

For reading a capture someone sent you, usually yes, and without installing anything or trusting an upload form. For live capture it cannot compete at all: a browser has no packet-capture API, so this tool only opens files that something else recorded. Wireshark also has decryption with supplied keys, expert analysis across thousands of protocol dissectors, and Lua extensibility. This page aims at the common case — open the file, find the packet, read the bytes — and is honest about where that case ends.

## Related tools

- [Subnet Calculator](https://bytescope.dev/en/subnet-calculator.md) — Work out which subnet the addresses in a capture belong to.
- [Certificate Decoder](https://bytescope.dev/en/certificate-decoder.md) — Paste a certificate seen in a TLS handshake and read it in full.
- [WebRTC Test](https://bytescope.dev/en/webrtc-test.md) — Check the connection itself before blaming the capture.
- [Hex Editor](https://bytescope.dev/en/hex-editor.md) — Open the raw bytes of any file with the same hex pane.
