Skip to content

Browser Support

Chrome 4+ · Firefox 4+ · Safari 4+ · Edge 12+ All modern browsers support it, including mobile.

Overview ​

HTTP is a "question-and-answer" pattern: client sends request, server returns response, then connection closes. Want the server to push messages to the browser? Can't do it.

WebSocket solves this. After HTTP handshake it upgrades to a persistent bidirectional channel — client and server can send messages at any time, no need to re-establish connection.

In short: Want the server to proactively send messages to the browser? WebSocket is the answer.

Essential Differences from HTTP ​

HTTPWebSocket
Connection directionClient initiatesBoth can initiate
Who speaks firstClientEither party
Connection lifecycleOpen per requestMaintained after handshake
Communication formatRequest/response textMessage frames (text or binary)
Header overheadFull headers per requestAlmost no headers after handshake
Use casesREST API, file retrievalReal-time push, collaboration, gaming

Quick Start ​

js
// Establish connection
const ws = new WebSocket('wss://echo.websocket.org');

ws.onopen = () => {
  console.log('Connection established');
  ws.send('Hello, server');  // Send message
};

ws.onmessage = (e) => {
  console.log('Received:', e.data);  // Received: Hello, server
};

ws.onerror = (e) => {
  console.error('WebSocket error:', e);
};

ws.onclose = () => {
  console.log('Connection closed');
};

wss:// is the encrypted version (equivalent to HTTPS), must use it in production.

Core Concepts ​

URL Format ​

ws://  localhost:8080/chat      # Plain text, not recommended
wss:// example.com/chat         # Encrypted, recommended

Path (/chat) is determined by server, same semantic as HTTP routing.

Connection Establishment ​

Client                              Server
  |                                   |
  |--- HTTP GET + Upgrade header ----->|
  |<-- 101 Switching Protocols -------|
  |                                   |
  |========= WebSocket Connection =====|
  |<========= Bidirectional msgs =====|
  |========= Bidirectional msgs =====>|
  |                                   |
  |--- Close frame ------------------->|
  |<-- Close frame -------------------|

Server returns 101 Switching Protocols indicates successful handshake, then enters WebSocket protocol.

Subprotocol ​

If multiple logics need to run on the same TCP connection (e.g. chat + game), subprotocol can be negotiated during handshake:

js
const ws = new WebSocket('wss://example.com', ['graphql-ws', 'mqtt']);

Server picks one and returns it in Sec-WebSocket-Protocol header, both sides parse message format per agreed subprotocol.

Heartbeat ​

TCP itself doesn't sense if peer is alive (e.g. pulling the network cable doesn't immediately trigger TCP error). Heartbeat mechanism needed:

  • Client periodically sends a ping message, server replies pong
  • If no message received for a while, connection is considered dead
  • WebSocket protocol has no built-in ping/pong, implement it at application layer or use frame types 0x9 / 0xA

Browser auto-handles

Browser auto-replies 0xA (pong) when receiving 0x9 (ping) frame, no manual handling needed.

Notes ​

  • Must be HTTPS/WSS: Modern browsers have strict restrictions on WebSocket in non-secure contexts (except localhost)
  • Server needs support too: WebSocket is a protocol, requires server cooperation (Node.js, Go, Python, etc.)
  • Not needed for all scenarios: If only need "client polls server", Server-Sent Events (SSE) is simpler
  • Doesn't self-heal: Browser doesn't auto-reconnect after disconnect, must implement reconnection logic yourself

Released under the MIT License.