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 |
|---|---|---|
seek | number | Seek button duration in seconds (default: 10) |
autoplay | boolean | Auto-start playback (default: true) |
muted | boolean | Start muted (default: false) |
color | hex | Accent color (use %23 for #) |
controls | boolean | Show player controls (default: true) |
back | string | URL for back button, or "close" to send a close event |
autonext | boolean | Auto-play next episode (default: true) |
autoskip | boolean | Auto-skip intro/recap when detected (default: false) |
prioritize | boolean | Prioritize the last used source on load (default: false) |
lastserver | string | Source ID to use as the preferred source |
t / time | number | Start time in seconds |
continueprompt | boolean | Show continue/restart prompt (default: true) |
quality | string | Preferred 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:ready | — | Player loaded and ready |
nebula:play | — | Playback started |
nebula:pause | — | Playback paused |
nebula:timeupdate | { currentTime, duration } | Periodic time update |
nebula:seeking | { currentTime, duration } | User started seeking |
nebula:seeked | { currentTime, duration } | Seek operation completed |
nebula:ended | — | Playback 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:close | — | Back 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 |
|---|---|---|---|
play | — | Promise | Start playback |
pause | — | void | Pause playback |
seek | time: number | void | Seek to time in seconds |
setVolume | vol: number | void | Set volume (0-1) |
setMuted | muted: bool | void | Mute/unmute |
setPlaybackRate | rate: number | void | Set speed (0.25-2) |
getCurrentTime | — | number | Get current playback time in seconds |
getDuration | — | number | Get total media duration |
getVolume | — | number | Get current volume |
getMuted | — | boolean | Get current muted state |
getPaused | — | boolean | Get current paused state |
getPlaybackRate | — | number | Get 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_id | number | TMDB identifier for the movie or TV show |
s | number TV only | Season number, starting from 1 |
e | number TV only | Episode 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:errorevents 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.