One connection, not one request
A WebSocket starts as an ordinary HTTP request — a GET with an Upgrade: websocket header — and if the server agrees, that single HTTP exchange turns into a long-lived, bidirectional connection that can stay open for the rest of the session. After the upgrade, there's no more request/response pairing at all: either side can send a message at any time, in any order, and the connection just stays open until something closes it.
This is exactly the property that makes WebSockets useful — a chat app or a live price feed doesn't want to poll — and exactly the property that makes them awkward to inspect with tools built around REST's request-then-response shape.
What "debugging it" actually means here
With a REST request, the questions are usually: what was sent, what came back, what was the status code. None of those quite apply to a WebSocket. The equivalent questions are:
- Did the upgrade handshake actually succeed, or is the app silently falling back to polling?
- Once open, is anything being sent at all, in either direction — or is the connection just sitting idle?
- When a message arrives, which direction did it go, and how does its timing relate to whatever the user just did?
- Did the connection close cleanly (a close frame with a reason code), or did it just drop?
Reading an individual frame
Frames come in a few kinds worth telling apart: text frames (almost always JSON in practice), binary frames (anything from a compact custom protocol to binary-encoded protobuf), and control frames — ping/pong, used to keep the connection alive and detect a dead one, and close, which carries a status code explaining why the connection ended. A connection that closes with code 1006 (abnormal closure, no close frame at all) points at a network-level drop; a clean 1000 or 1001 means the app or server intentionally ended it.
Why silence is a real symptom, not a missing feature
The most common WebSocket bug isn't a malformed message — it's nothing arriving at all, and a request/response-shaped tool has no way to represent "nothing happened" as a finding. If you're watching a WebSocket connection and expecting a message that never comes, that absence is the bug, and it's worth confirming the connection is actually still open (not silently closed) before assuming the server just hasn't sent anything yet.
Hollowport's WebSocket inspection shows individual frames, direction and all, the same way HTTP requests appear in Capture.