WebSockets
WebSockets allow you to communicate in real time with your Cloudflare Workers serverless functions. For a complete example, refer to Using the WebSockets API.
// { 0: <WebSocket>, 1: <WebSocket> }let websocketPair = new WebSocketPair();The WebSocketPair returned from this constructor is an Object, with two WebSockets at keys 0 and 1.
These WebSockets are commonly referred to as client and server. The below example combines Object.values and ES6 destructuring to retrieve the WebSockets as client and server:
let [client, server] = Object.values(new WebSocketPair());-
accept(options?)- Accepts the WebSocket connection and begins terminating requests for the WebSocket on Cloudflare's global network. This effectively enables the Workers runtime to begin responding to and handling WebSocket requests.
-
optionsobject optional-
An optional configuration object with the following properties:
allowHalfOpenboolean optional — Whentrue, the runtime will not automatically send a reciprocal Close frame when a Close frame is received from the peer. Instead,readyStateremainsCLOSINGuntil you explicitly callclose(). This is useful for WebSocket proxying where you need to coordinate the close across both sides of the proxy. Defaults tofalse.
-
-
addEventListener(eventWebSocketEvent, callbackFunctionFunction)- Add callback functions to be executed when an event has occurred on the WebSocket.
-
eventWebSocketEvent- The WebSocket event (refer to Events) to listen to.
-
callbackFunction(messageMessage)Function- A function to be called when the WebSocket responds to a specific event.
-
close(codenumber, reasonstring)- Close the WebSocket connection.
-
codeintegeroptional- An integer indicating the close code sent by the server. This should match an option from the list of status codes ↗ provided by the WebSocket spec.
-
reasonstringoptional- A human-readable string indicating why the WebSocket connection was closed.
-
send(messagestring | ArrayBuffer | ArrayBufferView)- Send a message to the other WebSocket in this WebSocket pair.
-
messagestring- The message to send down the WebSocket connection to the corresponding client. This should be a string or something coercible into a string; for example, strings and numbers will be simply cast into strings, but objects and arrays should be cast to JSON strings using
JSON.stringify, and parsed in the client.
- The message to send down the WebSocket connection to the corresponding client. This should be a string or something coercible into a string; for example, strings and numbers will be simply cast into strings, but objects and arrays should be cast to JSON strings using
-
readyStatenumber-
Returns the current state of the WebSocket connection. Possible values:
Constant Value Description WebSocket.CONNECTING0The connection is not yet open. WebSocket.OPEN1The connection is open and ready to communicate. WebSocket.CLOSING2The connection is in the process of closing. WebSocket.CLOSED3The connection is closed.
-
-
close- An event indicating the WebSocket has closed. The
CloseEventincludescode(number),reason(string), andwasClean(boolean) properties.
- An event indicating the WebSocket has closed. The
-
error- An event indicating there was an error with the WebSocket.
-
message- An event indicating a new message received from the client, including the data passed by the client.
dataany - The data passed back from the other WebSocket in your pair.typestring - Defaults tomessage.
With the web_socket_auto_reply_to_close compatibility flag (enabled by default on compatibility dates on or after 2026-04-07), the Workers runtime automatically sends a reciprocal Close frame when it receives a Close frame from the peer. The readyState transitions to CLOSED before the close event fires. This matches the WebSocket specification ↗ and standard browser behavior.
If you still call close() inside the close event handler, the call is silently ignored. Existing code that manually replies to Close frames will continue to work without changes.
server.addEventListener("close", (event) => { // readyState is already CLOSED — no need to call server.close(). console.log(server.readyState); // WebSocket.CLOSED console.log(event.code); // 1000 console.log(event.wasClean); // true});The automatic close behavior can interfere with WebSocket proxying, where a Worker sits between a client and a backend and needs to coordinate the close on both sides independently. To support this, pass { allowHalfOpen: true } to accept():
server.accept({ allowHalfOpen: true });
server.addEventListener("close", (event) => { // readyState is still CLOSING here, giving you time // to coordinate the close on the other side. console.log(server.readyState); // WebSocket.CLOSING
// Manually close when ready. server.close(event.code, "done");});On compatibility dates before 2026-04-07 (or with the web_socket_manual_reply_to_close flag), receiving a Close frame leaves the WebSocket in CLOSING state, and your code must call close() to complete the handshake. Failing to do so can result in 1006 abnormal closure errors on the client.