WebSockets Cheatsheet

Basics

Use this WebSockets reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

What WebSockets Are

A WebSocket is a full-duplex, persistent TCP connection between a client and server established via an HTTP/1.1 upgrade handshake. After the handshake, either side can send frames at any time with negligible overhead.

PropertyHTTP (REST)WebSocket
DirectionClient-initiated onlyBidirectional
ConnectionNew per requestPersistent
Overhead per messageFull HTTP headers2–14 byte frame header
Protocolhttp:// / https://ws:// / wss://
Port80 / 44380 / 443 (same)

The Handshake

The client sends a standard HTTP GET with upgrade headers; the server responds 101 Switching Protocols.

Client request (auto-sent by the browser WebSocket constructor):

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

Server response:

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

The Sec-WebSocket-Accept value is base64(SHA-1(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")). Libraries handle this automatically.

URL Schemes

// Unencrypted (development only)
const ws = new WebSocket("ws://localhost:4000/chat");

// TLS-encrypted (always use in production)
const ws = new WebSocket("wss://api.example.com/chat");

// With path and query params
const ws = new WebSocket("wss://api.example.com/ws?token=abc&room=42");

// With subprotocols (negotiated during handshake)
const ws = new WebSocket("wss://api.example.com/ws", ["v1.chat", "json"]);

Connection Lifecycle

Client                              Server
  |                                   |
  |--- HTTP Upgrade Request --------> |
  |<-- 101 Switching Protocols ------|
  |                                   |
  |<---------- open event ----------->|
  |                                   |
  |--- message frame --------------->|
  |<---------- message frame --------|
  |                                   |
  |--- close frame (code, reason) -->|
  |<---------- close frame ----------|
  |                                   |
  |          [TCP closed]            |

Four events fire on both sides:

EventWhen
openHandshake complete, connection ready
messageA frame arrives
errorProtocol or network error
closeConnection closed (always fires after error)

Frame Types

WebSocket messages are transported as frames. You never manipulate frames directly — the API handles framing.

OpcodeTypeNotes
0x0ContinuationFragment continuation
0x1TextUTF-8 string
0x2BinaryArrayBuffer / Blob
0x8CloseOptional 2-byte status code + reason
0x9PingKeepalive sent by either side
0xAPongAuto-reply to ping

Close Codes

ws.close(1000, "Normal closure");      // planned shutdown
ws.close(1001, "Going away");          // page navigating away
ws.close(1008, "Policy violation");    // auth failure / bad message
ws.close(1011, "Internal server error");
CodeMeaning
1000Normal closure
1001Endpoint going away (browser tab close)
1002Protocol error
1003Unsupported data
1005No status (reserved, never send)
1006Abnormal closure (reserved, never send)
1007Invalid frame payload data
1008Policy violation
1009Message too big
1011Internal server error
4000–4999Application-defined

Subprotocol Negotiation

// Client requests one or more protocols
const ws = new WebSocket("wss://example.com/ws", ["json-rpc", "msgpack"]);

// After open, check which one the server chose
ws.addEventListener("open", () => {
  console.log(ws.protocol); // e.g. "json-rpc" or ""
});

On the server (ws library):

wss = new WebSocketServer({
  server,
  handleProtocols(protocols, req) {
    if (protocols.has("json-rpc")) return "json-rpc";
    return false; // reject
  },
});

Key Gotchas

  • wss:// is required in production — mixed-content rules block ws:// on HTTPS pages.
  • The browser WebSocket API does not expose request headers; pass auth tokens via query string or a cookie.
  • Messages are delivered in order but the protocol does not guarantee delivery on abnormal close — design for idempotency or use sequence numbers.
  • Proxies and load balancers must support WebSocket upgrade; configure proxy_read_timeout in nginx or idle_timeout in AWS ALB (default 60 s is often too short).
  • The server must consume messages as fast as they arrive; a slow consumer stalls the TCP receive buffer, triggering backpressure.