Library / SDK
versatica/JsSIP avatar
versatica/JsSIP

JsSIP: a JavaScript SIP library for WebRTC calls in the browser and Node.js

JsSIP, the JavaScript SIP library

2,608 stars794 forksJavaScriptNOASSERTION

At a glance

What is it?
JsSIP puts a SIP user agent inside JavaScript, carrying signalling over WebSocket while WebRTC handles the media. This review covers what it does, how to install and make a first call, and where it stops being the right tool.
Who is it for?
Adopt JsSIP when your signalling server already speaks SIP over WebSocket, because the library assumes that transport and will not bridge to a plain UDP or TCP SIP endpoint. Skip it when you need a media stack, a gateway, or a server-side SIP proxy, since JsSIP is a client library only.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 149 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 October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What JsSIP is for, and who ends up using it

JsSIP is a JavaScript SIP library that runs in the browser and in Node.js. Its stated purpose is to let web applications place audio and video calls and send instant messages using real SIP signalling, rather than a proprietary signalling layer. The README lists SIP over WebSocket, WebRTC audio and video, instant messaging, and interoperability with Kamailio, Asterisk, Mobicents and repro (reSIProcate) servers.

The audience is narrow but well defined. You are building a web client, a softphone page, or a Node.js service that needs to register with a SIP registrar and place or receive calls. Your server side already exists and already terminates SIP. JsSIP is the client half of that arrangement. It is not a PBX, not a media server, and not a gateway that converts between transports.

The authorship is worth noting because it explains the design. The project says it was written by the authors of RFC 7118, the document that defines using the WebSocket protocol as a transport for SIP, and of mediasoup. That background shows in the API: the library models SIP concepts directly, with a UA object, sessions, and event handlers named after SIP call states such as progress, confirmed and ended.

How the WebSocket transport and the UA object fit together

The architecture is a thin SIP stack on top of a WebSocket connection. You construct a WebSocketInterface pointing at a wss:// URL, hand it to a UA instance together with a SIP URI and password, and call start(). From that point the UA owns registration and incoming requests, and ua.call() creates an outgoing session.

Media never passes through the socket. The signalling travels over WebSocket, and the audio and video path is negotiated separately through WebRTC. That split is why the README can claim "use real SIP in your web apps" while the media stays peer to peer or relayed by an ICE server that you configure elsewhere. The library's own dependencies are small: package.json lists debug, events and sdp-transform. SDP manipulation is the interesting one, since offer and answer bodies have to be built and rewritten as the session negotiates.

Call state is exposed through event handlers rather than promises or a state machine you query. You pass an eventHandlers object into ua.call(), and each named handler fires on a SIP outcome. This is an event-driven design, and it means error handling lives in the failed handler, where the cause arrives as e.data.cause. If you are used to awaiting a call result, this will feel inverted at first.

Installing JsSIP from npm and placing a first call

The README gives one install command. It publishes to npm under the name jssip, so the package manager is the entry point:

bash
npm install jssip

After installation, the library is imported and a UA is built from a WebSocket interface. The README's getting started example is the reference for the shape of the configuration object:

javascript
var socket = new JsSIP.WebSocketInterface('wss://sip.myhost.com');
var configuration = {
  sockets  : [ socket ],
  uri      : 'sip:[email protected]',
  password : 'superpassword'
};

var ua = new JsSIP.UA(configuration);

ua.start();

The sockets array holds the WebSocketInterface, uri is the SIP address of the account, and password is its credential. Calling ua.start() begins registration against whatever server the wss:// URL points at. If the URL or credentials are wrong, nothing in this snippet tells you; you find out through the UA's connection and registration events, which are documented on the project site rather than in the README.

Outgoing calls attach handlers for the states you care about, and media is requested through mediaConstraints:

javascript
var options = {
  eventHandlers,
  mediaConstraints: { 'audio': true, 'video': true }
};

var session = ua.call('sip:[email protected]', options);

The eventHandlers object in the README registers progress, failed, ended and confirmed. The failed and ended handlers both read e.data.cause, which is the SIP reason the call did not connect or terminated. Setting video to true in mediaConstraints asks for a video stream; the README does not state what happens when the remote party offers audio only, so treat mixed-media negotiation as something to confirm against your own server.

There is also an online demo at tryit.jssip.net, which the README links, and full documentation at jssip.net. The package.json points types at lib/JsSIP.d.ts and main at lib/JsSIP.js, so TypeScript consumers get declarations from the published package rather than from a separate types package.

The server requirement is not optional

The most consequential limitation is stated plainly in the README: SIP over WebSocket. A conventional SIP server listening on UDP or TCP port 5060 will not work. Your server must accept a WebSocket connection and speak SIP inside it. Kamailio, Asterisk, Mobicents and repro are named as compatible, and the project links an interoperability page for the details, but the compatibility list is not the same as a configuration guide. Getting the server side right is work that JsSIP does not do for you.

A second boundary is the media path. JsSIP negotiates WebRTC sessions, but the README does not describe ICE, STUN or TURN configuration. In a network with symmetric NAT or a restrictive firewall, a peer-to-peer media path may fail even when signalling succeeds, and the library's own documentation is where that configuration would live. If your deployment cannot reach a TURN relay, calls can register and ring and then produce no audio.

The event-handler model is a third place where the wrong tool becomes obvious. There is no built-in reconnection policy described in the README, no retry configuration, and no documented rollback or migration guidance in the README or the repository files. Anything about recovering a dropped WebSocket, re-registering after a network change, or handling token expiry is application logic you write on top.

Finally, the licence field in package.json says MIT while the repository metadata reports NOASSERTION. The README and package.json both point to MIT, and the project links jssip.net/license, but the discrepancy between the two sources is worth resolving before you rely on the licence in a compliance review.

JsSIP compared with SIP.js and sipml5

The comparison people search for most is JsSIP against SIP.js. Both are JavaScript SIP stacks that run over WebSocket and hand media to WebRTC, so the difference is not in the transport model. It is in the API surface and the maintenance arrangement. SIP.js exposes a session-oriented API with its own conventions for transports and user agents, and its documentation and release cadence differ from JsSIP's. Choosing between them usually comes down to which API your team can read faster and which one your SIP server vendor has already tested against. The README does not compare the two, so treat any claim about relative performance as unverified.

sipml5 is the older option, and the difference in approach is structural. sipml5 was built around the WebRTC plugin era, where the browser needed an add-on to reach the media APIs, and it ships as a packaged client with its own UI layer. JsSIP is a library you import into your own application and drive with your own interface. If you want a ready-made softphone page, sipml5's packaging is closer to that. If you want SIP calls inside an existing single-page application, JsSIP's model fits without dragging a UI along.

There is also the Node.js angle. JsSIP states that it runs in Node.js as well as the browser, which opens the option of a server-side SIP client. That is a different use case from a browser softphone, and it is worth checking whether your Node runtime provides the WebRTC pieces your scenario needs, since the README does not enumerate them.

Maintenance, versioning and what an upgrade costs

The repository is not archived, and the last push was on 2026-05-06. The published version in package.json is 3.13.8. The version number tells you something useful: this is a mature 3.x line, not a project churning through breaking changes. The dependency list is short and stable, with debug, events and sdp-transform as runtime dependencies, which limits the surface that can break under you.

Upgrade cost is mostly about the API you have already written against. The event-handler names and the UA configuration keys shown in the README are the contract, and a major version bump is where those would move. The CHANGELOG.md file at the repository root is the place to check before upgrading, and BUILDING.md covers the build. The npm scripts are wrapped in npm-scripts.mjs rather than being plain commands, so if you build from source you run the project's own script runner instead of calling a bundler directly.

On licence, package.json declares MIT and the README says the project is released under the MIT license, linking jssip.net/license. The repository metadata field reads NOASSERTION, which typically means the hosting platform could not classify the file automatically rather than that the terms are unknown. Confirm the LICENSE.md contents yourself if your organisation requires it; this is a description of what the files say, not legal advice.

Editorial conclusion

Adopt JsSIP when your signalling server already speaks SIP over WebSocket, because the library assumes that transport and will not bridge to a plain UDP or TCP SIP endpoint. Skip it when you need a media stack, a gateway, or a server-side SIP proxy, since JsSIP is a client library only. Before committing, verify that your server supports SIP over WebSocket, that your target browsers expose the WebRTC APIs the library depends on, and that your build toolchain handles the lib/ output and the bundled TypeScript declarations.

Frequently asked questions

What is the difference between WebRTC and SIP, and where does JsSIP sit?

SIP is the signalling protocol that sets up, modifies and tears down a session, while WebRTC carries the audio and video media. JsSIP handles the SIP side over a WebSocket connection and leaves the media to WebRTC, which is why the README describes it as using real SIP in web apps.

How does JsSIP compare with SIP.js?

Both are JavaScript SIP libraries that signal over WebSocket and use WebRTC for media, so the transport model is the same. The practical difference is the API shape and the documentation each project ships; the JsSIP README does not compare the two, so the choice usually follows whichever API your team reads faster and whatever your SIP server has been tested against.

How does JsSIP compare with sipml5?

sipml5 ships as a packaged client with its own interface, while JsSIP is a library you import and drive from your own application code. If you need a ready-made softphone page, sipml5's packaging is closer; if you need SIP inside an existing web app, JsSIP's model avoids carrying a UI with it.

Official sources

  1. Issues
  2. Project website
  3. README
  4. versatica/JsSIP 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/versatica-jssip.svg)](https://hysenlabs.com/projects/versatica-jssip)