9 min
  • WebSockets
  • HTTP
  • TCP/IP

The upgrade, and the frames after it

A WebSocket does not start as a WebSocket. It starts as an ordinary HTTP/1.1 GET on port 443, with a few fields that ask the server to stop speaking HTTP.

http
GET /chat HTTP/1.1Host: example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Version: 13 HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 

That blank line after the 101 is the same framing device from track 4, doing its last job: it is the exact byte at which HTTP ends and frames begin.

Loading the WebSocket Viewer simulation…

Why it looks like HTTP at all

Because that is what deploys. A WebSocket connection traverses corporate proxies, load balancers and firewalls that have never heard of WebSockets, precisely because the first thing they see is a GET to port 443 with a Host field.

Sec-WebSocket-Accept is the server hashing the client's key together with a fixed, published GUID. It is not a secret and proves nothing about identity — it is a proof of comprehension, showing that whatever answered actually understood the request rather than a cache replaying an old 101.

Check yourself
Sec-WebSocket-Accept is computed from a public constant. What is it for?

Frames, and the message that spans several

After the 101 there is no request/response pairing at all — just two independent streams of frames sharing one socket. A frame is a couple of bytes of header and then payload, which is why a chat message costs about eleven bytes total.

A message is not a frame. A sender that does not yet know how long its message will be can start sending anyway: the first frame carries the type with FIN clear, every frame after it carries the continuation opcode, and the last one sets FIN.

Loading the WebSocket Viewer simulation…

The length field has three encodings — 0–125 inline, then 126 meaning "the real length is in the next two bytes" and 127 meaning "the next eight" — and the encoding must be minimal, because two legal spellings of one frame is how parsers come to disagree.

Loading the WebSocket Viewer simulation…
Predict what happens next
A team sends binary data over a WebSocket by base64-encoding it into text frames. What does that cost?

Key takeaways

  • A WebSocket begins as an ordinary GET on port 443, which is exactly why it deploys through infrastructure that knows nothing about it.
  • The blank line ending the 101 response is the precise byte where HTTP stops and framing begins.
  • Sec-WebSocket-Accept proves comprehension, not identity — the GUID it hashes is published in the RFC.
  • After the upgrade there is no request/response pairing: two independent streams of frames share one socket.
  • A message may span several frames, and binary frames exist so bytes need not be base64-encoded into text ones.

Take it further