Library / SDK
sockjs/sockjs-client avatar
sockjs/sockjs-client

SockJS client example: one WebSocket-shaped object and a server you have to run

WebSocket emulation - Javascript client

8,504 stars1,270 forksJavaScriptMIT

At a glance

What is it?
SockJS-client hands browser code a WebSocket-shaped object that tries native WebSockets first and several browser transports second, which buys you coverage behind restrictive proxies at the price of a SockJS counterpart on the server and a published release that stopped at 1.6.1 in 2022.
Who is it for?
Adopt sockjs-client when your users sit behind proxies that block the WebSocket protocol and you can commit to running a SockJS server such as SockJS-node, since the fallback chain is the only reason the client exists. Skip it on a clean network where the platform WebSocket API already works, where a server counterpart buys nothing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 23 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • sockjs/sockjs-client8,504 ★ · +3
Star history
Repository2026-09-222026-11-14
sockjs/sockjs-client8.5k8.5k

3 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Where the options go: the middle constructor argument is reserved

Every connection begins at `new SockJS(url, _reserved, options)`. The middle slot is spelled `_reserved`, which says the argument is held for future use rather than something you set today. Configuration belongs in the third argument, and four keys are given there: `server`, `transports`, `sessionId` and `timeout`.

The URL is where this client parts company with `WebSocket`. You pass an ordinary HTTP URL, `https://mydomain.com/my_prefix` in the project's own example, and it may carry a query string if you want one. SockJS then appends per-connection routing on top of that URL, and a SockJS server has to be listening on the result. That requirement surfaces in the first line of application code: the object cannot be pointed at an endpoint that only speaks plain WebSocket.

Callbacks are assigned the way they are on the platform object. Set `onopen`, `onmessage` and `onclose`, and the stated design aim is that the API follows the HTML5 Websockets API as closely as possible.

Native WebSocket first, browser-specific transports after that

Under the hood the client tries native WebSockets and falls back to browser-specific transport protocols only when that fails, presenting all of them through WebSocket-like abstractions. That order is the reason to reach for the library. Browsers on open networks take the fast path, and the fallback earns its keep in environments without the WebSocket protocol, the case named in the README being restrictive corporate proxies.

The fallback set is treated as a requirement rather than an apology. All transports must support cross-domain connections out of the box, hosting the SockJS server on a different server than your main web site is called possible and recommended, and at least one streaming protocol per major browser is expected. Streaming transports are expected to work cross-domain and to support cookies, which is what makes cookie-based sticky sessions possible. Polling transports exist for old browsers and for hosts behind restrictive proxies.

One old setup cost is gone by design: no Flash inside, so nothing has to open port 843, nothing has to host a `crossdomain.xml`, and nobody waits three seconds to find out that something is broken.

One script tag and three callbacks gets a connection open

The library ships as a browser file, and the way to get it is a script tag in the HTML head pointing at a copy of the published bundle on jsdelivr:

html
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>

`package.json` names `dist/sockjs.min.js` as the jsdelivr entry, and the `dist/` directory is committed to the repository, so the tag resolves to a file that already exists rather than something built on the reader's machine.

With that file loaded, a connection is three callbacks:

javascript
 var sock = new SockJS('https://mydomain.com/my_prefix');
 sock.onopen = function() {
     console.log('open');
     sock.send('test');
 };

 sock.onmessage = function(e) {
     console.log('message', e.data);
     sock.close();
 };

 sock.onclose = function() {
     console.log('close');
 };

The example sends `test` from `onopen`, logs whatever arrives in `onmessage`, then closes. No plugin, no hand-built socket URL. The address is plain HTTP rather than `ws://`, and the `/my_prefix` path belongs to a SockJS endpoint that has to be running.

The `server` option defaults to a random four digit path

Three of the four documented options change where traffic goes or how long the client waits, and each has a default worth knowing.

`server` is a string appended to the URL for the actual data connection, and the default is a random four digit number. Left alone, every page load lands on a different path suffix. A proxy rule, WAF rule or CDN configuration that allowlists one SockJS path is therefore wrong on each reload unless you pin the value yourself.

`transports` takes a string or an array of strings and acts as an allowlist: every available transport may be used by default, and this key narrows that set. It is not a command to select one transport.

`timeout` sets a minimum in milliseconds for transport connections. Omit it and the value is calculated dynamically from the measured RTT and the number of expected round trips, so setting it raises the floor rather than replacing that calculation.

A custom `sessionId` function is used as-is on both sides

`sessionId` is the option with the most room to break something. Pass a number and SockJS uses its random string generator to produce identifiers of that length. Pass a function and it gets called every time an identifier is needed, with the returned string used directly and no further processing. The requirement on that function takes one line: it must return a randomly generated string.

Both client and server use session identifiers to tell connections apart, which is why damage from a careless generator shows up on the server side. A function returning a counter, a millisecond timestamp, or the same constant in two tabs does not meet the README's requirement of a randomly generated string. Leaving the option unset is the safer route, since the default is eight character identifiers from the built-in generator.

A plain WebSocket server will never answer this client

Weigh this before anything else in an evaluation. SockJS-client does require a server counterpart, and the one named in the README is SockJS-node for Node.js. The address you hand the constructor is an HTTP URL owned by a SockJS endpoint, not a `ws://` or `wss://` URL that any WebSocket server would accept. That is a deployment decision, not a line of code.

You either run a SockJS server implementation or choose a framework that already speaks the protocol. The family list spans Node, Erlang, Python through Cyclone and Twisted, Tornado, Twisted and Aiohttp, a Java client and server inside the Spring Framework, vert.x, Scala's Xitrum, Atmosphere, and Actix SockJS on Rust. A second list, marked work in progress, covers Ruby, Netty, gevent, Pyramid, Perl, Go and a .NET port, so outside the first list your server side is a community project with its own release history.

Cookies deserve the same scrutiny. Streaming transports should support cookies for cookie-based sticky sessions, and that promise is not extended to polling transports, which are the ones that survive the restrictive proxies that make you want this library in the first place.

Against the platform WebSocket API the difference is one of approach. Native WebSocket is a single transport with no counterpart library on the server and an outright failure where the protocol is blocked. SockJS keeps the same object shape and adds a fallback chain, paid for with the server counterpart.

Manifest says 1.6.2, newest release tag says 1.6.1 from 2022

Read the version numbers before pinning anything. The recent releases are v1.6.1 on 2022-05-28, v1.6.0 on 2022-02-27 and v1.5.2 on 2021-08-24. The last push was on 2026-10-22 and `package.json` declares version 1.6.2, so the source tree has moved past the newest tag without cutting a release. Installing from npm gives you the 2022 code while the manifest in the repository claims something newer.

The development toolchain did move. `devDependencies` carries mocha at ^11.1.0 and esbuild at ^0.28.1 while `engines` still asks for Node >=12, and the `browser` field maps Node core modules onto project files: `events` to `./lib/event/emitter.js`, `crypto` to `./lib/utils/browser-crypto.js`, `eventsource` to `./lib/transport/browser/eventsource.js`, and the transport drivers to their browser counterparts. Those shims are what let one tree serve both a browser and the karma suite.

The licence is MIT. Commercial support and maintenance are pointed at a Tidelift subscription instead of a paid tier inside the package.

Editorial conclusion

Adopt sockjs-client when your users sit behind proxies that block the WebSocket protocol and you can commit to running a SockJS server such as SockJS-node, since the fallback chain is the only reason the client exists. Skip it on a clean network where the platform WebSocket API already works, where a server counterpart buys nothing. Before you pin a version, check which build you actually get: the newest release tag is v1.6.1 from 2022-05-28 while the repository manifest declares 1.6.2.

Frequently asked questions

What is sockjs client and when does it earn its place?

SockJS-client is a browser JavaScript library that provides a WebSocket-like object. It tries native WebSockets first and falls back to browser-specific transport protocols through the same abstraction, which is what makes it usable behind restrictive corporate proxies. It requires a SockJS server counterpart, and the README names SockJS-node for Node.js.

Can sockjs-client connect to a plain WebSocket server?

No. SockJS-client does require a server counterpart, and the one named in the README is SockJS-node. You connect to an HTTP URL such as https://mydomain.com/my_prefix rather than a ws:// address, so an endpoint that only speaks plain WebSocket will not answer it.

Which options can I pass to the sockjs-client constructor?

Options go in the third argument of `new SockJS(url, _reserved, options)`. `server` is appended to the URL and defaults to a random four digit number, `transports` is an allowlist that narrows the available transports, `sessionId` sets identifier length or supplies a generator function, and `timeout` sets a minimum in milliseconds, otherwise calculated from the measured RTT and expected round trips.

Which published version of sockjs-client should I pin?

The newest release listed for the repository is v1.6.1 from 2022-05-28, while `package.json` declares version 1.6.2 and the last push was on 2026-10-22. Pinning to what npm serves gives you the 2022 code, not the current tree.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. sockjs/sockjs-client on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sockjs-sockjs-client.svg)](https://hysenlabs.com/projects/sockjs-sockjs-client)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/sockjs-sockjs-client.svg)](https://hysenlabs.com/projects/sockjs-sockjs-client)

Was this useful?