Skip to main content
Daily supports two fundamental integration modes. The mode you choose determines how much UI Daily renders versus how much you build yourself.

Iframe Mode

Daily renders a full call UI inside an <iframe>. Best for fast integration with minimal custom UI work.

Call Object Mode

Headless — Daily manages WebRTC and media, but you build every pixel of UI. Maximum flexibility.

Iframe Mode

In iframe mode, Daily creates an <iframe> element and loads its full prebuilt call UI inside it. You interact with the call through the Daily JavaScript API, but the camera tiles, controls, and layout all live inside the iframe. This mode is ideal when:
  • You want a working video call in minutes
  • Custom branding is handled via themes rather than custom components
  • You’re embedding a call widget into an existing page

Factory methods

Three factory methods create iframe-backed instances:
createFrame() creates and appends a new <iframe> element. Optionally accepts a parent element and/or properties object.
// Appends iframe to document.body with a default floating style
const call = Daily.createFrame();

// Appends iframe to a specific container
const call = Daily.createFrame(
  document.getElementById('call-container'),
  { showFullscreenButton: false }
);
When parentEl is document.body, the default iframeStyle is a fixed-position widget (375×450 px, bottom-right). When a custom container is provided the iframe stretches to fill it (width: 100%; height: 100%; border: 0).

Full iframe example

import Daily from '@daily-co/daily-js';

const call = Daily.createFrame(
  document.getElementById('call-container'),
  {
    url: 'https://your-domain.daily.co/hello',
    showLeaveButton: true,
    iframeStyle: {
      width: '100%',
      height: '100%',
      border: '0',
    },
  }
);

call.on('joined-meeting', (event) => {
  console.log('Joined!', event.participants);
});

await call.join();

Call Object Mode

Call object mode is headless. Daily loads its media engine but renders no UI. Your application receives participant state and media tracks, and you render everything yourself. This mode is created with createCallObject():
static createCallObject(properties?: DailyFactoryOptions): DailyCall

Call object example

import Daily from '@daily-co/daily-js';

const call = Daily.createCallObject({
  url: 'https://your-domain.daily.co/hello',
  subscribeToTracksAutomatically: true,
});

// You handle all rendering
call.on('track-started', ({ participant, track, type }) => {
  if (type === 'video' && !participant?.local) {
    const videoEl = document.createElement('video');
    videoEl.autoplay = true;
    videoEl.srcObject = new MediaStream([track]);
    document.getElementById('video-grid')?.appendChild(videoEl);
  }
});

call.on('track-stopped', ({ track }) => {
  // remove video element whose srcObject contains this track
});

await call.join();
Several properties are iframe-only and log a console error in call object mode: showLocalVideo, showParticipantsBar, activeSpeakerMode, customTrayButtons, customIntegrations.Conversely, receiveSettings is only available in call object mode.

Choosing a Mode

CriterionIframe ModeCall Object Mode
Time to first callMinutesHours–days
Custom UILimited (CSS + themes)Full control
Track accessVia eventsVia events + direct MediaStreamTrack
React / custom framework integrationModerateNative

Next steps

Prebuilt UI

Learn what Daily Prebuilt offers out of the box — themes, custom buttons, language settings, and more

API Reference

Explore the full factory method and instance method reference for DailyCall