twilio-video.js: Twilio's JavaScript SDK for WebRTC rooms
Twilio’s Programmable Video JavaScript SDK
At a glance
- What is it?
- twilio-video.js is Twilio's browser SDK for its Programmable Video service, giving a JavaScript application a connect call, participant and track events, and media attachment for voice and video rooms over WebRTC. It suits a team that has decided on Twilio's rooms and signalling, and it is the wrong choice if you want a peer-to-peer WebRTC stack with no vendor in the middle.
- Who is it for?
- twilio-video.js fits a product team that has already chosen Twilio Programmable Video and wants the browser side of it without assembling a signalling protocol, an SFU and a media pipeline by hand, since the SDK ships the room model, the track publication and subscription lifecycle, and the attachment helpers.
- 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 13 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A room model rather than a peer connection
twilio-video.js is Twilio's Programmable Video JavaScript SDK, and the one-line description is that it lets you add real-time voice and video to your web apps. What matters more is the shape of the API it exposes.
The unit of work is a Room, not a peer connection. You call Video.connect with a token and a room name, and you get back a room object with participants, events and local tracks. Other people appear as RemoteParticipant objects. Media arrives as tracks attached to publications, and each publication has a lifecycle with subscribed and unsubscribed events. There is no peer-to-peer mesh to assemble and no offer and answer exchange to write.
That abstraction is the whole trade. A direct WebRTC library gives you the transport and leaves you to solve signalling, room membership, media server topology and reconnect behaviour. This SDK assumes Twilio's infrastructure handles those, and exposes the application-facing concerns instead.
The trade-off follows directly from that. The library is useful only alongside Twilio's Programmable Video service, since the token, the room name and the media routing all refer to Twilio's backend. If your requirement is a peer-to-peer call between two browsers with no third-party server in the path, this is the wrong shape of tool and a general WebRTC library is the right one.
The SDK is JavaScript with TypeScript definitions, published on npm as twilio-video, with the docs at sdk.twilio.com. The homepage for the service documentation is twilio.com/docs/video/javascript.
Installing from npm or pulling a pinned build from the CDN
There are two documented installation routes, and the second one exists for a reason worth knowing about.
From npm:
npm install twilio-video --savewhich gives you a CommonJS require, and TypeScript definitions that can be imported either wholesale or piecemeal:
import * as Video from 'twilio-video';
function participantDisconnected(participant: Video.RemoteParticipant) {
console.log('Participant "%s" disconnected', participant.identity);
document.getElementById(participant.sid).remove();
}The second route is the CDN, and the version in the URL is pinned to a release:
<script src="//sdk.twilio.com/js/video/releases/2.36.1/twilio-video.min.js"></script>Loading that way sets a browser global rather than a module, so the code refers to Twilio.Video instead of the imported namespace. Pinning the version in the URL is the pattern to notice: a CDN script tag without a version would give you whatever is current at page load, which is exactly the failure mode a production deployment does not want.
The release sequence in the repository is recent and regular: 2.35.0 from 2026-04-30, 2.36.0 from 2026-09-15 and 2.36.1 from 2026-10-09, with the last push to the repository on the same day as the 2.36.1 release. The version in package.json is 2.36.2-dev, so the development branch carries the next patch already.
For a team running this in production, the practical question is not which route to use but how the two relate to each other. An application that loads from npm and an application that loads from the CDN are on different upgrade schedules, and mixing the two in one codebase is a support problem waiting to happen.
The connect-and-listen pattern the examples teach
The readme's usage example is worth reading closely, because it shows the event model that the rest of the SDK is built around.
The connection is a promise. Video.connect takes a token and a room name, and resolves to a room:
const Video = require('twilio-video');
Video.connect('$TOKEN', { name: 'room-name' }).then(room => {
console.log('Connected to Room "%s"', room.name);
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', error => room.participants.forEach(participantDisconnected));
});Two details carry the design. First, the existing participants are iterated before the event handler is attached, so that a participant who joined before you connected is not missed. Second, the disconnected handler is registered with once rather than on, because the room ending is terminal and the example uses it to clean up remaining participants.
Tracks are handled at the participant level. A participant emits trackSubscribed and trackUnsubscribed, and each participant also has a tracks collection whose publications carry an isSubscribed flag, which is how the example attaches media that was already available at connection time.
The attachment model is the part that touches the DOM. A subscribed track is attached with track.attach(), which returns a media element, and detaching is track.detach() returning an array of elements to remove. The example pairs the two by keeping the element inside a per-participant div whose id is the participant sid.
The readme links a quickstart and examples repository, a React-based multi-party video application, and the API docs. It also links COMMON_ISSUES.md in the repository for known problems, which for a media library is usually where the practical answers are.
Browser support, and the gaps in the matrix
The readme publishes a support matrix by browser and platform, and it is worth reading rather than assuming.
Chrome is the only browser with a tick in every column: Windows, macOS, Linux, iOS and Android. Firefox covers Windows, macOS, Linux and Android but not iOS. Edge covers Windows, macOS and iOS but not Linux or Android. Safari covers macOS and iOS but not Windows. Samsung Internet covers Android only, and WebView covers iOS only.
The practical consequences are sharper than the tick marks suggest. If your audience includes Windows desktop users on Safari, or Android users on Edge, or iOS users in an embedded WebView, the SDK is not for them. The iOS WebView entry in particular is narrow: an in-app browser on iOS is supported and the plain mobile browsers are not, so a product that has to run inside a native app shell on Android needs a different plan.
There is also a WebRTC platform reality behind the matrix, and it is the reason mobile Safari behaves differently: Safari on iOS has historically required the app to be served over HTTPS for camera and microphone access to work at all, which is a deployment constraint rather than an SDK limitation but has the same effect on whether your product runs.
The linked best practices guide on the Twilio documentation site covers the application-side recommendations, and the common issues document covers the SDK-side ones. Between them they are the practical reference for the browsers that are not in the table, since the table only tells you what is supported.
Content Security Policy, and the noise-cancellation exception
The readme has a section on making Content Security Policy work with the SDK, and the directives are specific enough to be worth copying rather than reconstructing.
The base policy needs the signalling and media endpoints opened up:
connect-src wss://global.vss.twilio.com wss://sdkgw.us1.twilio.com
media-src mediastream:The media-src mediastream: directive is what lets the browser attach captured camera and microphone streams, and the connect-src entries are the WebSocket endpoints the SDK talks to.
If you load the SDK from sdk.twilio.com rather than bundling it, the script-src directive has to allow that origin:
script-src https://sdk.twilio.comAnd there is one exception worth flagging, because it is the kind of directive that gets added by someone in a hurry. If you enable Krisp Noise Cancellation for local audio and you use a default-src self directive, the readme says you should also add unsafe-eval:
default-src self unsafe-evalunsafe-eval weakens the policy for the whole page, not just for the SDK, so treating it as a scoped exception is not possible. If your security review is strict about eval, that is a constraint to weigh against the noise cancellation feature, and the readme does not offer an alternative.
The readme also notes that you may need to merge these directives with your own if you use other services, which is the usual situation and the usual source of a broken deployment.
Where twilio-video.js is the wrong tool
The first limitation is the vendor dependency, and it is not a small one. The room model only works because Twilio's infrastructure provides the media server and the signalling. If your requirement includes routing media peer to peer, or keeping audio and video off a third-party network, or running without a Twilio account and a per-participant-minute bill, then this SDK is the wrong tool regardless of how good its event model is.
The second is the licence and commercial terms. The licence on this repository is one GitHub cannot classify, with the terms in LICENSE.md at the root, and the SDK is only useful together with a paid Twilio service. Neither of those is a technical objection, but both belong in the evaluation before anyone writes code against the API, because the API surface is a commitment: connecting to a room is a Twilio concept, and moving later means rewriting that layer.
The third is the browser coverage. The matrix has real holes, and they are holes in your audience rather than in the SDK's quality. A product targeting Windows Safari users, or Android Edge, or iOS WebView, needs another approach for those platforms, and a video SDK that works for 70 percent of your users is not the same as one that works for all of them.
The fourth is that this is the browser side only. There is a Twilio Programmable Video server SDK for the media server role and the client SDK is JavaScript for the browser; a team that also needs iOS or Android native clients is looking at other Twilio SDKs, and a team that needs a native mobile app with the same features has to plan for that separately.
The fifth is the age of the API surface. The repository's related section points at a Twilio Video React application, a JavaScript quickstart and a diagnostics app, and the SDK follows a room-and-participant model that has been stable for years. That stability is a virtue for an existing application. For a new project, it is also worth checking against what the current Twilio documentation recommends, since the SDK version and the service version are separate things and the readme links to both.
Editorial conclusion
twilio-video.js fits a product team that has already chosen Twilio Programmable Video and wants the browser side of it without assembling a signalling protocol, an SFU and a media pipeline by hand, since the SDK ships the room model, the track publication and subscription lifecycle, and the attachment helpers. It is the wrong choice if you want direct peer-to-peer calls without a media server in the path, and it is the wrong choice if the Twilio licence terms or the cost of the service do not suit your usage. Before adopting it, check the browser support table against your audience, since Edge is not supported on Linux or Android and Safari is not supported on Windows, and note that the last push was on 2026-10-09 with 2.36.1 released the same day under the terms in LICENSE.md.
Frequently asked questions
How do I install twilio-video.js?
Run npm install twilio-video --save and then require it with const Video = require('twilio-video'). Alternatively, include the CDN build with a pinned version, for example a script tag pointing at //sdk.twilio.com/js/video/releases/2.36.1/twilio-video.min.js, which sets a browser global at Twilio.Video.
How do I connect to a Twilio Video room with twilio-video.js?
Call Video.connect with an access token and a room name, for example Video.connect('$TOKEN', { name: 'room-name' }), which resolves to a room object. You then iterate room.participants for those already present and register room.on for participantConnected and participantDisconnected.
Which browsers does twilio-video.js support?
The readme publishes a matrix: Chrome is supported on Windows, macOS, Linux, iOS and Android, Firefox on Windows, macOS, Linux and Android, Edge on Windows, macOS and iOS, Safari on macOS and iOS, Samsung Internet on Android, and WebView on iOS.
What Content Security Policy does twilio-video.js need?
The readme gives connect-src for the Twilio signalling endpoints and media-src mediastream:, plus a script-src directive for https://sdk.twilio.com if you load the SDK from the CDN. If you enable Krisp Noise Cancellation with a default-src self policy, the readme says to add unsafe-eval.
What licence is twilio-video.js released under?
The licence is one GitHub cannot classify, with the terms in the LICENSE.md file at the root of the repository. The last push was on 2026-10-09 and the newest published release is 2.36.1 from the same day, with 2.36.0 from 2026-09-15 before it.
Official sources
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.
[](https://hysenlabs.com/projects/twilio-twilio-video-js)Was this useful?