Documentation · v3.0

Nebula Embed API

A TMDB-powered media player that you can embed into any website. Drop in an iframe and control playback with our postMessage API.

Quickstart

Embed the player into your site using an iframe. Point src to a Nebula embed URL with a TMDB ID.

Movie
<iframe
  src="https://nebuladb.pages.dev/embed?movie={tmdb_id}"
  width="100%" height="100%"
  frameborder="0" allowfullscreen
  allow="autoplay; fullscreen; picture-in-picture"
></iframe>
TV Show
<iframe
  src="https://nebuladb.pages.dev/embed?tv={tmdb_id}&s={season}&e={episode}"
  width="100%" height="100%"
  frameborder="0" allowfullscreen
  allow="autoplay; fullscreen; picture-in-picture"
></iframe>

URL Structure

All content is identified by TMDB IDs. Find any ID on themoviedb.org — it's in the URL when you view a title.

Movies
GET https://nebuladb.pages.dev/embed?movie={tmdb_id}
TV Shows
GET https://nebuladb.pages.dev/embed?tv={tmdb_id}&s={season}&e={episode}

URL Customization

Customize player behavior with URL parameters:

Parameter Type Description
seeknumberSeek button duration in seconds (default: 10)
autoplaybooleanAuto-start playback (default: true)
mutedbooleanStart muted (default: false)
colorhexAccent color (use %23 for #)
controlsbooleanShow player controls (default: true)
backstringURL for back button, or "close" to send a close event
autonextbooleanAuto-play next episode (default: true)
autoskipbooleanAuto-skip intro/recap when detected (default: false)
prioritizebooleanPrioritize the last used source on load (default: false)
lastserverstringSource ID to use as the preferred source
t / timenumberStart time in seconds
continuepromptbooleanShow continue/restart prompt (default: true)
qualitystringPreferred video quality ("1080", "720", "480")
Example
<iframe src="https://nebuladb.pages.dev/embed?tv=31132&s=1&e=1&seek=15&autoplay=true&color=ff5722&autoskip=true"></iframe>

Player Events

Listen for events via postMessage to sync your application with the player.

Event Listener Setup
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://nebuladb.pages.dev') return;
  
  const { type, ...data } = event.data;
  
  switch (type) {
    case 'nebula:ready':
      console.log('Player ready');
      break;
    case 'nebula:timeupdate':
      console.log(data.currentTime, '/', data.duration);
      break;
  }
});
Available Events
Event Data Description
nebula:readyPlayer loaded and ready
nebula:playPlayback started
nebula:pausePlayback paused
nebula:timeupdate{ currentTime, duration }Periodic time update
nebula:seeking{ currentTime, duration }User started seeking
nebula:seeked{ currentTime, duration }Seek operation completed
nebula:endedPlayback ended
nebula:volumechange{ volume, muted }Volume changed
nebula:ratechange{ playbackRate }Playback speed changed
nebula:loadedmetadata{ duration }Media metadata loaded
nebula:nextepisode{ season, episode }Auto-navigated to next episode
nebula:skipintro{ time }Intro skipped, seeked to specified time
nebula:sourceused{ sourceId }Stream source changed
nebula:closeBack button clicked when back=close
nebula:error{ error }Error occurred
nebula:response{ command, result }Response to a getter command

Player Methods

Control the player programmatically by sending commands via postMessage.

Sending Commands
const iframe = document.querySelector('iframe');

function sendCommand(command, args = []) {
  iframe.contentWindow.postMessage({
    type: 'nebula:command',
    command,
    args
  }, 'https://nebuladb.pages.dev');
}

// Examples
sendCommand('play');
sendCommand('pause');
sendCommand('seek', [120]);
sendCommand('setVolume', [0.5]);
Available Methods
Method Parameters Returns Description
playPromiseStart playback
pausevoidPause playback
seektime: numbervoidSeek to time in seconds
setVolumevol: numbervoidSet volume (0-1)
setMutedmuted: boolvoidMute/unmute
setPlaybackRaterate: numbervoidSet speed (0.25-2)
getCurrentTimenumberGet current playback time in seconds
getDurationnumberGet total media duration
getVolumenumberGet current volume
getMutedbooleanGet current muted state
getPausedbooleanGet current paused state
getPlaybackRatenumberGet current playback speed
Getter Response Example
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://nebuladb.pages.dev') return;
  if (event.data.type !== 'nebula:response') return;

  switch (event.data.command) {
    case 'getCurrentTime':
      console.log('Current time:', event.data.result);
      break;
  }
});

Content Parameters

Parameter Type Description
tmdb_idnumberTMDB identifier for the movie or TV show
snumber TV onlySeason number, starting from 1
enumber TV onlyEpisode number, starting from 1

Advanced Usage

For fully responsive embeds, wrap the iframe in a container with a fixed aspect ratio.

<div style="aspect-ratio: 16 / 9; width: 100%;">
  <iframe
    src="https://nebuladb.pages.dev/embed?movie=550"
    style="width: 100%; height: 100%; border: none;"
    allowfullscreen
    allow="autoplay; fullscreen; picture-in-picture"
  ></iframe>
</div>
Best Practices
  • Always verify message origin before processing postMessage events
  • Set iframe to 100% width/height and control size with parent container
  • Include allow="autoplay; fullscreen; picture-in-picture" on your iframe
  • Lazy-load iframe when it enters viewport for better performance
  • Listen for nebula:error events and provide fallback UI

Player Features

Play / Pause — Spacebar or click
Volume slider & Mute — M key
Customizable seek duration (URL param)
Fullscreen — F key
Picture-in-Picture
Playback speed — 0.5× to 2×
Multiple source support
Auto-play on source ready
Responsive — fits any container
Smart source caching
Auto-next episode (TV only)
Auto-skip intro/recap
Accent color customization
Full postMessage API

Notes

  • All content metadata is sourced from TMDB. Nebula is a metadata and discovery tool only.
  • TMDB IDs can be found on themoviedb.org — search any title and check the URL.
  • Season and episode numbers always use official numbering, starting from 1.
  • The embed is fully client-side — no server dependency for the end viewer.
  • Nebula does not store user data or require API keys.
  • Always verify event.origin in production for security.