NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #55 most downloaded on npm
Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js
Last release 8 days ago
26 Sep 2026
Release timing varies
gaps range from 1 weeks to 8 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
15 years old
189 releases · first in 2011
Introduced the protocols option ( 8b918b0 ).
The server now correctly rejects permessage-deflate offers if the incoming client_max_window_bits parameter value is smaller than its configured clien
client_max_window_bits parameter value is smaller than its configuredclientMaxWindowBits (e97a20e).One column per quarter.
Fixed a test for CITGM ( 2eb3be0 ).
Empty fragments are now counted toward the limit ( a2f4e7c ).
Fixed a remote memory exhaustion DoS vulnerability ( 2b2abd4 ).
maxBufferedChunks and maxFragments options (2b2abd4).A high volume of tiny fragments and data chunks could be sent by a peer, using
modest network traffic, to crash a ws server or client due to OOM.
import { WebSocket, WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 0 }, function () {
const data = Buffer.alloc(1);
const options = { fin: false };
const { port } = wss.address();
const ws = new WebSocket(`ws://localhost:${port}`);
ws.on('open', function () {
(function send() {
ws.send(data, options, function (err) {
if (err) return;
send();
});
})();
});
ws.on('error', console.error);
ws.on('close', function (code, reason) {
console.log(`client close - code: ${code} reason: ${reason.toString()}`);
});
});
wss.on('connection', function (ws) {
ws.on('error', console.error);
ws.on('close', function (code, reason) {
console.log(`server close - code: ${code} reason: ${reason.toString()}`);
});
});The vulnerability was responsibly disclosed and fixed by Nadav Magier.
In vulnerable versions, the issue can be mitigated by lowering the value of the
maxPayload option if possible.
Fixed an uninitialized memory disclosure issue in websocket.close() (c0327ec1).
websocket.close()
(c0327ec1).Providing a TypedArray (e.g. Float32Array) as the reason argument for
websocket.close(), rather than the supported string or Buffer types, caused
uninitialized memory to be disclosed to the remote peer.
import { deepStrictEqual } from 'node:assert';
import { WebSocket, WebSocketServer } from 'ws';
const wss = new WebSocketServer(
{ port: 0, skipUTF8Validation: true },
function () {
const { port } = wss.address();
const ws = new WebSocket(`ws://localhost:${port}`, {
skipUTF8Validation: true
});
ws.on('close', function (code, reason) {
deepStrictEqual(reason, Buffer.alloc(80));
});
}
);
wss.on('connection', function (ws) {
ws.close(1000, new Float32Array(20));
});
The issue was privately reported by Nikita Skovoroda.
Added exports for the PerMessageDeflate class and utilities for the Sec-WebSocket-Extensions and Sec-WebSocket-Protocol headers (d3503c1f).
PerMessageDeflate class and utilities for the
Sec-WebSocket-Extensions and Sec-WebSocket-Protocol headers (d3503c1f).Handled a forthcoming breaking change in Node.js core (19984854).
closeTimeout option (#2308).Fixed a spec violation where the Sec-WebSocket-Version header was not added to the HTTP response if the client requested version was either invalid or
Sec-WebSocket-Version header was not added
to the HTTP response if the client requested version was either invalid or
unacceptable (#2291).Fixed an issue that, during message decompression when the maximum size was exceeded, led to the emission of an inaccurate error and closure of the co
The length of the UNIX domain socket paths in the tests has been shortened to make them work when run via [CITGM][] (021f7b8b).
Added support for Blob (#2229).
Blob (#2229).Fixed a DoS vulnerability (#2231).
A request with a number of headers exceeding theserver.maxHeadersCount
threshold could be used to crash a ws server.
const http = require('http');
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 0 }, function () {
const chars = "!#$%&'*+-.0123456789abcdefghijklmnopqrstuvwxyz^_`|~".split('');
const headers = {};
let count = 0;
for (let i = 0; i < chars.length; i++) {
if (count === 2000) break;
for (let j = 0; j < chars.length; j++) {
const key = chars[i] + chars[j];
headers[key] = 'x';
if (++count === 2000) break;
}
}
headers.Connection = 'Upgrade';
headers.Upgrade = 'websocket';
headers['Sec-WebSocket-Key'] = 'dGhlIHNhbXBsZSBub25jZQ==';
headers['Sec-WebSocket-Version'] = '13';
const request = http.request({
headers: headers,
host: '127.0.0.1',
port: wss.address().port
});
request.end();
});
The vulnerability was reported by Ryan LaPointe in https://github.com/websockets/ws/issues/2230.
In vulnerable versions of ws, the issue can be mitigated in the following ways:
--max-http-header-size=size and/or the maxHeaderSize options so
that no more headers than the server.maxHeadersCount limit can be sent.server.maxHeadersCount to 0 so that no limit is applied.This is a breaking change in a patch release. The assumption is that the option is not widely used.
WebSocket constructor now accepts the createConnection option (#2219).allowSynchronousEvents option has been changed to
true (#2221).This is a breaking change in a patch release. The assumption is that the option is not widely used.
Added the autoPong option (01ba54ed).
autoPong option (01ba54ed).This is a breaking change in a patch release that could have been avoided with an alias, but the renamed option was added only 3 days ago, so hopefull…
allowMultipleEventsPerMicrotask option has been renamed to
allowSynchronousEvents (4ed7fe58).This is a breaking change in a patch release that could have been avoided with an alias, but the renamed option was added only 3 days ago, so hopefully it hasn't already been widely used.
Added the allowMultipleEventsPerMicrotask option (93e3552e).
allowMultipleEventsPerMicrotask option (93e3552e).Fixed an issue that allowed errors thrown by failed assertions to be swallowed when running tests (7f4e1a75).
Improved the reliability of two tests for [CITGM][] (fd3c64cb).
The WebSocket constructor now accepts HTTP(S) URLs (#2162).
WebSocket constructor now accepts HTTP(S) URLs (#2162).socket argument of server.handleUpgrade() can now be a generic
Duplex stream (#2165).Added the finishRequest option to support late addition of headers (#2123).
finishRequest option to support late addition of headers (#2123).Added browser condition to package.json (#2118).
browser condition to package.json (#2118).Added support for utf-8-validate@6 (ff63bba3).
utf-8-validate@6 (ff63bba3).buffer.isUtf8() is now used instead of utf-8-validate if available
(42d79f60).WebSocket.prototype.addEventListener() now supports an event listener specified as an object with a handleEvent() method. (9ab743aa).
WebSocket.prototype.addEventListener() now supports an event listener
specified as an object with a handleEvent() method. (9ab743aa).WebSocket.prototype.addEventListener() now adds an event listener only if it
is not already in the list of the event listeners for the specified event type
(1cec17da).Added an export for package.json (211d5d38).
Added the ability to connect to Windows named pipes (#2079).
The Authorization and Cookie headers are no longer sent if the original request for the opening handshake is sent to an IPC server and the client is r
Authorization and Cookie headers are no longer sent if the original
request for the opening handshake is sent to an IPC server and the client is
redirected to another IPC server (bc8bd34e).Added the WS_NO_BUFFER_UTIL and WS_NO_UTF_8_VALIDATE environment variables (becf237c).
WS_NO_BUFFER_UTIL and WS_NO_UTF_8_VALIDATE environment
variables (becf237c).Added the ability to inspect the invalid handshake requests and respond to them with a custom HTTP response. (6e5a5ce3).
Upgrade header field value in the HTTP
response is not a case-insensitive match for the value "websocket" (0fdcc0af).Authorization and Cookie headers are no longer sent when following an
insecure redirect (wss: to ws:) to the same host (d68ba9e1).Added the ability to remove confidential headers on a per-redirect basis (#2030).
Added the ability to use a custom WebSocket class on the server (#2007).
WebSocket class on the server (#2007).Authorization and Cookie headers are no
longer sent if the redirect host is different from the original host (#2013).Fixed a data framing issue introduced in version 8.4.1 (#2004).
To improve performance, strings sent via websocket.ping(), websocket.pong(), and websocket.send() are no longer converted to Buffers if the data does
websocket.ping(),
websocket.pong(), and websocket.send() are no longer converted to
Buffers if the data does not need to be masked (#2000).Added ability to generate custom masking keys (#1990).
Added ability to pause and resume a WebSocket (0a8c7a9c).
WebSocket (0a8c7a9c).When context takeover is enabled, messages are now compressed even if their size is below the value of the perMessageDeflate.threshold option (41ae563
perMessageDeflate.threshold option (41ae5631).Some closing operations are now run only if needed (ec9377ca).
Fixed an issue where the socket was not resumed, preventing the connection from being closed cleanly (869c9892).
Added WebSocket.WebSocket as an alias for WebSocket and WebSocket.WebSocketServer as an alias for WebSocket.Server to fix name consistency and improve
WebSocket.WebSocket as an alias for WebSocket and
WebSocket.WebSocketServer as an alias for WebSocket.Server to fix name
consistency and improve interoperability with the ES module wrapper (#1935).Fixed an issue with a breaking change in Node.js master (6a72da3e).
The WebSocket constructor now throws a SyntaxError if any of the subprotocol names are invalid or duplicated (0aecf0c9).
The WebSocket constructor now throws a SyntaxError if any of the
subprotocol names are invalid or duplicated (0aecf0c9).
The server now aborts the opening handshake if an invalid
Sec-WebSocket-Protocol header field value is received (1877ddeb).
The protocols argument of handleProtocols hook is no longer an Array but
a Set (1877ddeb).
The opening handshake is now aborted if the Sec-WebSocket-Extensions header
field value is empty or it begins or ends with a white space (e814110e).
Dropped support for Node.js < 10.0.0 (552b5067).
The WebSocket constructor now throws a SyntaxError if the connection URL
contains a fragment identifier or if the URL's protocol is not one of 'ws:',
'wss:', or 'ws+unix:' (ebea038f).
Text messages and close reasons are no longer decoded to strings. They are
passed as Buffers to the listeners of their respective events. The listeners
of the 'message' event now take a boolean argument specifying whether or not
the message is binary (e173423c).
Existing code can be migrated by decoding the buffer explicitly.
websocket.on('message', function message(data, isBinary) {
const message = isBinary ? data : data.toString();
// Continue as before.
});
websocket.on('close', function close(code, data) {
const reason = data.toString();
// Continue as before.
});
The package now uses an ES module wrapper (78adf5f7).
WebSocketServer.prototype.close() no longer closes existing connections
(df7de574).
Existing code can be migrated by closing the connections manually.
websocketServer.close();
for (const ws of websocketServer.clients) {
ws.terminate();
}
The callback of WebSocketServer.prototype.close() is now called with an
error if the server is already closed (abde9cfc).
WebSocket.prototype.addEventListener() is now a noop if the type argument
is not one of 'close', 'error', 'message', or 'open' (9558ed1c).
WebSocket.prototype.removeEventListener() now only removes listeners added
with WebSocket.prototype.addEventListener() and only one at time (ea95d9c4).
The value of the onclose, onerror, onmessage, and onopen properties is
now null if the respective event handler is not set (6756cf58).
The OpenEvent class has been removed (21e65004).
WebSocket.prototype.addEventListener()
(0b21c03a).Fixed a bug introduced in version 7.5.12 that prevented the fragment counter from resetting ( 18bcb11 ).
Backported a2f4e7c and f197ac6 to the v7.x release line ( fb8a193 , deec211 ).
Backported 2b2abd45 to the 7.x release line (e14c4586).
Backported e55e5106 to the 7.x release line (22c28763).
Backported bc8bd34e to the 7.x release line (0435e6e1).
Backported 0fdcc0af to the 7.x release line (2758ed35).
Backported 6946f5fe to the 7.x release line (1f72e2e1).
Backported b8186dd1 to the 7.x release line (73dec34b).
Backported ec9377ca to the 7.x release line (0e274acd).
Backported 6a72da3e to the 7.x release line (76087fbf).
The WebSocketServer constructor now throws an error if more than one of the noServer, server, and port options are specefied (66e58d27).
WebSocketServer constructor now throws an error if more than one of the
noServer, server, and port options are specefied (66e58d27).'close' event was emitted by a WebSocketServer before
the internal HTTP/S server was actually closed (5a587304).WebSocketServer.prototype.close() was called (772236a1).The opening handshake is now aborted if the client receives a Sec-WebSocket-Extensions header but no extension was requested or if the server indicate
Sec-WebSocket-Extensions header but no extension was requested or if the
server indicates an extension not requested by the client (aca94c86).Fixed an issue that prevented the connection from being closed properly if an error occurred simultaneously on both peers (b434b9f1).
Some errors now have a code property describing the specific type of error that has occurred (#1901).
code property describing the specific type of error
that has occurred (#1901).Fixed a ReDoS vulnerability (00c425ec).
A specially crafted value of the Sec-Websocket-Protocol header could be used
to significantly slow down a ws server.
for (const length of [1000, 2000, 4000, 8000, 16000, 32000]) {
const value = 'b' + ' '.repeat(length) + 'x';
const start = process.hrtime.bigint();
value.trim().split(/ *, */);
const end = process.hrtime.bigint();
console.log('length = %d, time = %f ns', length, end - start);
}
The vulnerability was responsibly disclosed along with a fix in private by Robert McLaughlin from University of California, Santa Barbara.
In vulnerable versions of ws, the issue can be mitigated by reducing the maximum
allowed length of the request headers using the --max-http-header-size=size
and/or the maxHeaderSize options.
UTF-8 validation is now done even if utf-8-validate is not installed (23ba6b29).
utf-8-validate is not installed
(23ba6b29).websocket.close() and websocket.terminate() did
not close the connection (67e25ff5).Fixed a bug that could cause the process to crash when using the permessage-deflate extension (92774377).
The deflate/inflate stream is now reset instead of reinitialized when context takeover is disabled (#1840).
Silenced a deprecation warning (a2c0d447).
Your coding agent can read these notes before it upgrades. Set up the MCP server →