WebSocket Protocol

Understanding how WebSocket works under the hood.

The Handshake

WebSocket connections start with an HTTP upgrade request. This is called the "opening handshake":

Client Request

GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 Sec-WebSocket-Protocol: chat, graphql-ws

Server Response

HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat

Key Headers

  • Upgrade: websocketRequests protocol upgrade from HTTP to WebSocket
  • Sec-WebSocket-KeyRandom Base64-encoded value for security verification
  • Sec-WebSocket-ProtocolOptional subprotocol(s) the client supports
  • Sec-WebSocket-AcceptServer's proof that it received the key (derived from key + magic string)

Frame Structure

After the handshake, data is transmitted in frames. Each frame has a specific structure:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

Frame Fields

  • FIN1 bit indicating this is the final fragment of a message
  • Opcode4 bits defining the frame type (see below)
  • MASK1 bit. Client frames must be masked (1), server frames are not (0)
  • Payload length7+ bits. If 0-125, that's the length. If 126, next 2 bytes are length. If 127, next 8 bytes.

Frame Types (Opcodes)

The opcode field determines how the payload should be interpreted:

OpcodeNameDescription
0x0ContinuationContinues a fragmented message
0x1TextUTF-8 encoded text data
0x2BinaryRaw binary data
0x8CloseConnection close request
0x9PingKeep-alive request
0xAPongKeep-alive response

Subprotocols

WebSocket subprotocols define application-level message formats on top of the WebSocket transport:

graphql-ws/ graphql-transport-ws

GraphQL over WebSocket protocol. Used for GraphQL subscriptions.

mqtt

MQTT (Message Queuing Telemetry Transport) over WebSocket for IoT applications.

stomp

STOMP (Simple Text Oriented Messaging Protocol) for message broker communication.

Note: The negotiated subprotocol is shown in the footer when connected. If the server doesn't support any of your requested protocols, the connection proceeds without a subprotocol.

Close Codes

When closing a connection, a status code indicates the reason:

CodeNameMeaning
1000Normal ClosureConnection closed normally
1001Going AwayServer shutting down or browser navigating away
1002Protocol ErrorInvalid frame received
1003Unsupported DataReceived data type not supported
1006Abnormal ClosureConnection lost without close frame
1008Policy ViolationMessage violates server policy
1011Internal ErrorUnexpected server error

Security Considerations

  • Always use wss://: In production, always use encrypted WebSocket (wss://) to prevent eavesdropping and man-in-the-middle attacks.
  • Origin checking: Servers should validate the Origin header to prevent cross-site WebSocket hijacking.
  • Authentication: Authenticate during handshake (headers) or immediately after connection (first message).
  • Input validation: Always validate and sanitize incoming messages on both client and server.
  • Rate limiting: Implement rate limiting to prevent DoS attacks through message flooding.

References

  • RFC 6455 - The WebSocket Protocol
  • MDN WebSocket API Documentation
  • IANA WebSocket Protocol Registry