Skip to main content

What is daily-js?

daily-js (@daily-co/daily-js) is Daily’s JavaScript library that lets you embed WebRTC-based video and audio calls into any web application. It handles all the complexity of WebRTC — signaling, media negotiation, network traversal, device handling,and more — so you can focus on building your product.

Key features

Participant management

Track participants, control audio/video, manage permissions, and handle waiting rooms

Device management

Error handling, automatic device switching, and permission management — abstracted across browsers with their differing specs, bugs, and quirks

Recording

Cloud and local recording with custom layout presets and compositing

Live streaming

Stream to any RTMP endpoint with multiple layout options

Transcription

Real-time transcription powered by Deepgram with language and model selection

Media processing

Background blur and virtual backgrounds via Banuba, plus AI noise cancellation via Krisp

Custom tracks

Send custom audio and video tracks alongside camera/mic streams

Network diagnostics

Monitor network quality and run pre-call connectivity tests

Integration modes

daily-js supports two primary ways to integrate video calls into your app:

Iframe mode (Prebuilt UI)

Daily manages a full-featured call UI inside an <iframe>. You get a complete video call experience — participant tiles, controls, chat, and more — with minimal code.
const callFrame = Daily.createFrame();
await callFrame.join({ url: 'https://your-domain.daily.co/room-name' });
Best for: teams that want a working video call UI quickly, or want to embed Daily’s Prebuilt UI.

Call object mode (Headless)

Daily manages audio/video streams with no UI of its own. You have full control over the participant interface and can build any custom design.
const callObject = Daily.createCallObject();
await callObject.join({ url: 'https://your-domain.daily.co/room-name' });
Best for: teams building fully custom video UIs or integrating Daily into existing interfaces.

How it works

The @daily-co/daily-js npm package is a small orchestration layer — it does not contain the full call machinery. When you call join() (or load() if you pre-load ahead of time), the SDK fetches a call bundle from Daily’s CDN. That bundle contains the WebRTC engine, media pipeline, and everything else needed to run the call. This keeps your application’s initial bundle size minimal, but it means:
  • A network request happens on first join. The loading and loaded events mark the start and end of this fetch.
  • If the fetch fails, load-attempt-failed fires and a few retries are attempted before an error event is emitted.
  • You can call load() before join() to fetch the bundle early and hide the loading latency from users.

Iframe mode and Prebuilt

In iframe mode, there are actually two daily-js instances in play. The one you import and interact with in your app is the outer orchestration layer. Inside the <iframe>, Daily’s Prebuilt UI runs its own separate daily-js instance — the one that directly manages WebRTC, devices, and media. Your calls (join(), setLocalVideo(), etc.) are forwarded into the iframe via postMessage. Events from the inner instance are forwarded back out the same way, which is why you can listen for them on the outer call object just like in call object mode. Because the inner instance is served directly from Daily’s CDN rather than from your npm dependency, the two versions may not be identical — but they are tested for compatibility. This also means that in Prebuilt, you’re always running Daily’s latest Prebuilt release, and frequently ahead of what’s published to npm.

Call lifecycle

1

Create

Call one of the factory methods to create a DailyCall instance. No network activity starts yet.
2

Join

Call call.join({ url }). Daily fetches the call bundle, connects to the room, and meeting state transitions through joining-meetingjoined-meeting.
3

In call

Participant and track events fire. Your application renders media and handles interactions.
4

Leave

Call call.leave() to disconnect. Meeting state becomes left-meeting. The instance is reusable — you can call join() again.
5

Destroy

Call call.destroy() to release all resources. In iframe mode, this also removes the iframe from the DOM. After this the instance must not be used.

Next steps

Quickstart

Get a working video call running in under 5 minutes

Installation

Install daily-js via npm/yarn or a CDN script tag

Call Modes

Choose between iframe-based or headless call object mode

API Reference

Explore the full API surface