WebSocket
WebSocket is a communications protocol providing full-duplex, bidirectional communication over a single TCP connection. The protocol operates over HTTP ports 80 and 443, maintaining compatibility with existing HTTP infrastructure including proxies and intermediaries.
- Usage
- URI schemes
- Establishing a connection over HTTP/1.1
- Establishing a connection over HTTP/2
- Establishing a connection over HTTP/3
- WebSocket headers
- Sec-WebSocket-Extensions example
- Sec-WebSocket-Protocol
- Sec-WebSocket-Protocol example
- Sec-WebSocket-Version
- Sec-WebSocket-Version example
- Framing
- Accessing WebSocket programmatically
- Takeaway
- See also
Baseline: Widely available
Supported in all major browsers. webstatus.dev
Usage
WebSocket and HTTP are distinct protocols sharing the same underlying transport infrastructure. The WebSocket protocol addresses a core limitation of HTTP: the lack of persistent, bidirectional communication.
With HTTP, a client such as a web-based chat application must continuously poll the server for new messages. Each poll creates a new request, and in some configurations, a new connection. WebSocket maintains a single long-lived connection for the duration of the session, eliminating the overhead of repeated connection setup and teardown.
Because WebSocket connections ride on existing HTTP infrastructure, proxies, load balancers, and Authentication schemes work without major changes. The protocol is independent of HTTP at the data-transfer level. Once established, WebSocket frames flow directly over TCP without HTTP framing.
URI schemes
The WebSocket protocol defines two URI schemes:
ws:// for unencrypted connections and wss:// for
WebSocket Secure connections encrypted with
TLS.
ws://authority/path?query
wss://authority/path?query
No fragment support
WebSocket URIs follow standard URI syntax
but do not support the fragment component (#).
Well-known URIs
The well-known URI mechanism
extends to the ws and wss schemes. The list of
registered well-known URIs is maintained by
IANA.
Establishing a connection over HTTP/1.1
The HTTP/1.1 protocol provides a mechanism for upgrading an existing connection to WebSocket using the HTTP Upgrade request header. The client sends an HTTP GET request with the Upgrade and Connection headers to signal a protocol switch.
The server is not obligated to accept the upgrade, even when supporting the WebSocket protocol. The Upgrade header is hop-by-hop, meaning each intermediary along the path processes the header individually.
HTTP/1.1 handshake example
The client sends an HTTP request containing the
Upgrade header, the Connection
header with the Upgrade token, a Sec-WebSocket-Key,
and Sec-WebSocket-Version. The server responds with
101 Switching Protocols and includes
Sec-WebSocket-Accept to confirm the protocol switch.
Request
GET /chat HTTP/1.1
Host: www.example.re
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: http://example.re
Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
After the client verifies the Sec-WebSocket-Accept
value, subsequent data flows as WebSocket frames
rather than HTTP messages.
Establishing a connection over HTTP/2
HTTP/2 does not support connection-wide headers like Upgrade or status codes like 101. Instead, an extended CONNECT method opens a WebSocket tunnel on a single HTTP/2 stream.
The server advertises support by sending the
SETTINGS_ENABLE_CONNECT_PROTOCOL parameter (0x08) with
a value of 1. The client then sends a CONNECT request
with the :protocol pseudo-header set to websocket,
along with :scheme, :path, and :authority
pseudo-headers.
:method = CONNECT
:protocol = websocket
:scheme = https
:path = /chat
:authority = www.example.re
Sec-WebSocket-Version: 13
Origin: https://example.re
This approach allows WebSocket traffic to share a single TCP connection with regular HTTP/2 streams, benefiting from multiplexing, prioritization, and flow control.
Establishing a connection over HTTP/3
The same extended CONNECT mechanism applies to
HTTP/3. The semantics of the pseudo-headers and
the SETTINGS_ENABLE_CONNECT_PROTOCOL setting (0x08) are
identical to the HTTP/2 variant.
The main difference lies in stream closure. Orderly
closure maps to a FIN on the HTTP/3 stream, while
exceptional termination uses a stream error of type
H3_REQUEST_CANCELLED.
WebSocket headers
Several headers negotiate parameters during the opening handshake.
Sec-WebSocket-Key
The Sec-WebSocket-Key header carries a nonce consisting
of a randomly selected 16-byte value encoded in base64.
A fresh key is generated for each connection. The purpose
is not Authentication or privacy. Rather, the key
confirms the server understands the WebSocket
protocol and prevents intermediary caches from replaying
stale upgrade responses.
Sec-WebSocket-Accept
The Sec-WebSocket-Accept header
appears in the server response during the handshake.
The server concatenates the client Sec-WebSocket-Key
with the fixed GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11,
computes the SHA-1 hash of the result, and returns the
hash as a base64-encoded string.
Not a security mechanism
The Sec-WebSocket-Key / Sec-WebSocket-Accept
exchange verifies protocol understanding. A
different random key is sent for each connection so
cached responses from intermediaries are detected as
invalid.
Sec-WebSocket-Extensions
The Sec-WebSocket-Extensions header lets the client
request protocol-level extensions. Multiple extensions
are listed in a comma-delimited format, and each
extension accepts optional parameters separated by
semicolons.
The server responds with the same header, confirming which extensions will be active for the duration of the connection. Extensions are registered in the IANA WebSocket Extension Name Registry.
Sec-WebSocket-Extensions example
The most widely implemented extension is
permessage-deflate, which compresses message
payloads using the DEFLATE algorithm.
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol
The Sec-WebSocket-Protocol header lets the client
request a specific application-level subprotocol.
Multiple subprotocols are listed in order of preference,
either as separate header instances or in a
comma-delimited list. Subprotocols are registered in
the
IANA WebSocket Subprotocol Name Registry.
The server responds with a single
Sec-WebSocket-Protocol header confirming the selected
subprotocol.
Sec-WebSocket-Protocol example
A home automation network negotiates a subprotocol for
communicating with IoT devices. The preferred protocol
is SHIP (Smart Home IP), with done (done.best IoT
protocol) as a fallback.
Sec-WebSocket-Protocol: ship, done
Sec-WebSocket-Version
The Sec-WebSocket-Version header specifies which
WebSocket protocol version the client supports.
The value is a non-negative integer between 0 and 255.
The current standard version is 13.
When the server does not support the requested version,
the response includes Sec-WebSocket-Version listing
all versions the server accepts. The response status
code is typically 426 Upgrade Required.
Sec-WebSocket-Version example
The client requests version 13 (current standard) with version 8 as a fallback.
Sec-WebSocket-Version: 13, 8
If the server supports neither, a response indicates the versions available.
Response
HTTP/1.1 426 Upgrade Required
Sec-WebSocket-Version: 7, 6
Framing
Once the handshake completes, data travels in WebSocket frames rather than HTTP messages. Each frame carries an opcode identifying its type:
| Opcode | Type |
|---|---|
0x1 |
Text frame |
0x2 |
Binary frame |
0x0 |
Continuation frame |
0x8 |
Close |
0x9 |
Ping |
0xA |
Pong |
Text frames carry UTF-8 data. Binary frames carry arbitrary bytes. Close frames initiate a graceful shutdown and carry an optional two-byte status code followed by a UTF-8 reason string.
Ping and Pong frames serve as a keepalive mechanism. An endpoint receiving a Ping responds with a matching Pong.
Accessing WebSocket programmatically
WebSocket connections are created through the browser API or through server-side libraries.
const connection = new WebSocket(
'ws://files.example.re/'
);
Libraries for Java, C#, Python, Rust, Go, Ruby, and other languages provide equivalent functionality for connection management, message framing, and event handling.
Takeaway
The WebSocket protocol provides full-duplex, bidirectional communication over a single TCP connection. A connection is established through the HTTP/1.1 Upgrade mechanism, through the extended CONNECT method in HTTP/2 and HTTP/3, or programmatically through language-specific APIs.
See also
- RFC 6455: The WebSocket Protocol
- RFC 8441: Bootstrapping WebSockets with HTTP/2
- RFC 9220: Bootstrapping WebSockets with HTTP/3
- RFC 7692: Compression Extensions for WebSocket
- RFC 8307: Well-Known URIs for the WebSocket Protocol
- WebSocket Secure
- Protocol Upgrade
- Uniform Resource Identifier
- Well-Known URIs
- WebSocket Protocol Registries
- HTTP headers