websockets/ws · error · Error
ws does not work in the browser. Browser clients must use th
Error message
ws does not work in the browser. Browser clients must use the native WebSocket object
What it means
This error is thrown synchronously whenever the 'ws' module is imported in a browser bundle. The package.json declares a 'browser' field (and an exports.browser condition) that maps to browser.js, whose sole export is a function that throws this Error. Bundlers like webpack and vite resolve this stub automatically when the build target is a browser, replacing the full Node.js implementation. The library does this deliberately because ws depends on Node core modules (net, http, crypto) that cannot run in a browser environment.
Source
Thrown at browser.js:4
'use strict';
module.exports = function () {
throw new Error(
'ws does not work in the browser. Browser clients must use the native ' +
'WebSocket object'
);
};
View on GitHub (pinned to ae1de54330)
Solutions
- Replace `new WebSocket(...)` from ws with the browser-native `new WebSocket(url)` in any code that runs in the browser.
- If the module must be isomorphic, guard the import behind an environment check (typeof window !== 'undefined') and only require ws on the server side.
- Configure your bundler to alias 'ws' to a stub or to the native WebSocket only for browser builds, and keep the real ws for server builds.
- If you genuinely need ws in a browser-like environment (e.g. jsdom/electron renderer), ensure the bundler does not resolve the 'browser' condition — force Node resolution for that entry point.
Example fix
// before (shared module, breaks in browser)
const WebSocket = require('ws');
const ws = new WebSocket('ws://example.com');
// after (isomorphic — use native in browser, ws on server)
const WebSocket =
typeof window !== 'undefined'
? window.WebSocket
: require('ws');
const ws = new WebSocket('ws://example.com'); Defensive patterns
Strategy: validation
Validate before calling
// Detect a browser environment before importing ws
const isBrowser =
typeof window !== 'undefined' && typeof window.WebSocket !== 'undefined';
if (isBrowser) {
throw new Error(
'Use the native browser WebSocket (window.WebSocket) instead of the ws package.'
);
} Type guard
// Type guard for the browser-native WebSocket constructor
function isBrowserWebSocket(Ctor) {
return typeof Ctor === 'function' && Ctor.prototype && 'readyState' in Ctor.prototype;
} Try / catch
// Rarely useful: catching the throw from requiring ws in a browser bundle
let WebSocketImpl;
try {
WebSocketImpl = require('ws');
} catch (err) {
if (typeof window !== 'undefined') {
WebSocketImpl = window.WebSocket;
} else {
throw err;
}
} Prevention
- Never import 'ws' unconditionally in code that runs in a browser bundle — use environment guards or separate entry points.
- Configure your bundler (webpack resolve.fallback, vite resolve.alias) to exclude 'ws' for browser builds.
- In isomorphic libraries, export a factory that picks the native WebSocket in browsers and ws on the server.
- Review package.json 'browser' fields of dependencies when building for the browser.
When it happens
Trigger: A bundler (webpack/vite/rollup/esbuild) with a browser target resolves the 'browser' field in ws's package.json and substitutes browser.js for index.js. The throw fires the moment any code does `require('ws')` or `import ... from 'ws'` in the browser build. It also fires if a developer explicitly imports 'ws/browser.js'.
Common situations: A developer copies Node.js WebSocket client code into a frontend React/Vue/Angular project without switching to the browser-native WebSocket. A shared/isomorphic module unconditionally requires 'ws' and is bundled for the browser. A bundler misconfiguration where the 'browser' field resolves but no fallback shim is provided. Migrating a server-rendered app to client-side rendering.
Related errors
- Unexpected character at index ${i}
- Unexpected end of input
- None of the extension offers can be accepted
- Unexpected parameter "client_no_context_takeover"
- Unexpected or invalid parameter "client_max_window_bits"
AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03).
Data as JSON: /data/errors/ec529b1f7329accb.json.
Report an issue: GitHub.