A WebSocket is a handshake plus frames
6 min read
A WebSocket does not start as its own protocol. It starts as an ordinary HTTP GET with
an Upgrade: websocket header; the server answers 101 Switching Protocols, and
from that moment the same TCP connection stops speaking HTTP and starts carrying WebSocket
frames in both directions, whenever either side wants — no request/response pairing
anymore.
Each frame is tiny: a first byte with a FIN bit and an opcode (0x1 text, 0x2 binary, 0x8 close, 0x9/0xA ping/pong), a second byte with a MASK bit and the payload length, an optional 4-byte masking key, then the payload. One rule matters for reading captures: client-to-server frames are masked (XORed with that key, purely to defeat broken proxies — it is not encryption), and server-to-client frames are not. So anything the server pushes is plaintext on the wire, and anything the client sends is one trivial XOR away from it.
In Wireshark
- The connection appears first as an HTTP handshake — the
Upgraderequest and the101. That is your landmark. - After that, the display filter
websocketshows the frames. Wireshark unmasks client frames for you and shows the opcode, length, and payload in the detail tree. - Follow → TCP Stream still works, but the masked client frames look like noise there; the
websocketdissector is what makes them readable.
Because WS traffic is usually wss:// (TLS), reading someone else's needs the same
key-log trick as any HTTPS. Your own browser, your own machine — that is what the live lab is for.