← Add options bag to WebSocket constructor
v154 · experimental · constructor
WebSocket(url, protocolsOrOptions)
The WebSocket() constructor with its widened second parameter: a subprotocol string, an array of subprotocol strings, or — new in this feature — a WebSocketInit options dictionary. Connection semantics are otherwise unchanged from the classic constructor. Implemented in Chromium behind the experimental WebSocketOptionBag flag, targeted at Chrome 154.
Behind --enable-blink-features=WebSocketOptionBag (or chrome://flags/#enable-experimental-web-platform-features); the stable-promotion CL 8256918 and the defining spec change whatwg/websockets PR #76 are both open as of 2026-09-20. With the flag off, an options object coerces to the string "[object Object]" and the constructor throws SyntaxError. See the overview warn-block for a feature-detection pattern.
syntax
new WebSocket(url)
new WebSocket(url, protocols) // string or array — classic form
new WebSocket(url, options) // WebSocketInit dictionary — new
Proposed spec IDL (whatwg/websockets PR #76, quoted verbatim):
constructor(USVString url,
optional (DOMString or sequence<DOMString> or WebSocketInit) protocolsOrOptions = []);
Shipping Chromium IDL (websocket.idl at trunk, 2026-09-20 — quoted verbatim; the parameter is temporarily any so behavior can differ by flag state):
// The type of `protocolsOrOptions` is `any` because the type needs to
// differ depending on the setting of the "WebSocketOptionBag" feature.
// TODO(crbug.com/542670554): Change to `(DOMString or sequence<DOMString> or
// WebSocketInit)` when the "WebSocketOptionBag" feature is permanently
// enabled and removed.
[CallWith=ExecutionContext, RaisesException]
constructor(USVString url, optional any protocolsOrOptions);
Source: PR #76 diff; websocket.idl; crbug.com/542670554
parameters
url | USVString — the endpoint. Unchanged by this feature: ws, wss, http, and https schemes are allowed, fragments are not (per the living standard) |
|---|---|
protocolsOrOptions (optional) | One of: a subprotocol string (equivalent to a one-element array), a sequence of strings (any iterable of strings, most commonly an array), or a WebSocketInit dictionary whose protocols member supplies the same list. Defaults to [] (offer no subprotocol). Union routing follows Web IDL union conversion: strings take the DOMString branch, iterable objects the sequence branch, other objects the dictionary branch, and undefined the parameter default |
return value
A new WebSocket object in the CONNECTING state, exactly as the classic constructor returns; the connection is established asynchronously and open fires when the handshake (including subprotocol negotiation) completes. The server-selected subprotocol is then readable on socket.protocol. Which spelling supplied the protocols list is not observable on the returned object — { protocols: ["soap"] } and ["soap"] produce identical connections (in Chromium both feed the same Vector<String> handed to Connect() in dom_websocket.cc).
errors
SyntaxError DOMException | Unchanged host-constructor errors: a URL with a disallowed scheme or a fragment, or an invalid/duplicate subprotocol name — whichever branch supplied it. With the flag off, passing an options object lands here too: it coerces to "[object Object]", which is not a valid subprotocol token |
|---|---|
TypeError | A WebSocketInit whose protocols member is not an iterable object of strings — including the tempting bare string { protocols: "soap" } — fails Web IDL sequence conversion before any network activity |
SecurityError DOMException | Unchanged: ports blocked by the user agent (per the living standard) |
context and exposure
Exposed wherever WebSocket is exposed: Window and Worker contexts ([Exposed=(Window,Worker)] in both the spec PR and Chromium's IDL). The overload requires no permission, secure-context, or policy gate of its own — only the WebSocketOptionBag runtime flag in Chromium. The dictionary branch simply does not exist when the flag is off; there is no partial state.
lifecycle
- Script calls the constructor; the second argument is routed by union conversion (in Chromium:
V8UnionStringOrStringSequenceOrWebSocketInit::Create, thenParseConstructorOptionsWithBag()in dom_websocket.cc). - A dictionary's
protocolslist replaces the positional list; all later steps are the classic algorithm: validate protocols, open the handshake, fireopen/error/close. - The choice of spelling has no further lifecycle effect — reconnection, buffering,
close(), and events behave identically.
examples
// Feature-detect, then prefer the extensible form:
let socket;
try {
socket = new WebSocket("wss://example.com/feed", { protocols: ["v2.feed"] });
} catch {
// Older engine: object was coerced to "[object Object]" → SyntaxError.
socket = new WebSocket("wss://example.com/feed", ["v2.feed"]);
}
socket.addEventListener("open", () => {
console.log("negotiated subprotocol:", socket.protocol); // "v2.feed" or ""
});
Source: gendn-derived from the PR #76 semantics and the WPT negotiation test (labelled accordingly)
browser compatibility
Interim table. No BCD key for the overload (verified 2026-09-20); rows compiled from primary sources.
| Browser | Support | Evidence |
|---|---|---|
| Chrome / Edge (Chromium) | Implemented behind WebSocketOptionBag (experimental); stable promotion targeted at 154, pending as of 2026-09-20 | CL 8197225; flag record; CL 8256918 |
| Firefox | No signal | ChromeStatus API record; mozilla/standards-positions #1444 |
| Safari | Positive position, not shipped | WebKit/standards-positions #708 |
security and privacy
No new capability: the overload cannot reach any endpoint, port, or protocol the classic constructor cannot. The one behavioral delta is web-compat — a non-iterable object argument stops throwing SyntaxError and starts meaning “empty options”; the spec PR review is measuring how much shipping code relies on the old rejection before the change merges. Future dictionary members are individually security-reviewed (see targetAddressSpace on the WebSocketInit page).
see also
- Add options bag to WebSocket constructor — overview (feature page)
WebSocketInit— the dictionary this overload accepts- MDN — WebSocket() constructor (classic forms; no option-bag coverage, verified 2026-09-20)
- Chrome Platform Status — feature 5080055102439424
- Showcase — both argument forms demo (HEAD-checked 200, 2026-09-20)