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.
| Property | HTTP (REST) | WebSocket |
|---|---|---|
| Direction | Client-initiated only | Bidirectional |
| Connection | New per request | Persistent |
| Overhead per message | Full HTTP headers | 2–14 byte frame header |
| Protocol | http:// / https:// | ws:// / wss:// |
| Port | 80 / 443 | 80 / 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-Acceptvalue isbase64(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:
| Event | When |
|---|---|
open | Handshake complete, connection ready |
message | A frame arrives |
error | Protocol or network error |
close | Connection closed (always fires after error) |
Frame Types
WebSocket messages are transported as frames. You never manipulate frames directly — the API handles framing.
| Opcode | Type | Notes |
|---|---|---|
| 0x0 | Continuation | Fragment continuation |
| 0x1 | Text | UTF-8 string |
| 0x2 | Binary | ArrayBuffer / Blob |
| 0x8 | Close | Optional 2-byte status code + reason |
| 0x9 | Ping | Keepalive sent by either side |
| 0xA | Pong | Auto-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");
| Code | Meaning |
|---|---|
| 1000 | Normal closure |
| 1001 | Endpoint going away (browser tab close) |
| 1002 | Protocol error |
| 1003 | Unsupported data |
| 1005 | No status (reserved, never send) |
| 1006 | Abnormal closure (reserved, never send) |
| 1007 | Invalid frame payload data |
| 1008 | Policy violation |
| 1009 | Message too big |
| 1011 | Internal server error |
| 4000–4999 | Application-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 blockws://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_timeoutin nginx oridle_timeoutin 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.