One iframe
Movies, TV, and anime from a single embed. No SDK and no API key.
Beta Preview
Movies, shows, and anime — wrapped in one iframe, with servers, subtitles, and audio already inside.
Everything the player already does — without extra setup.
Movies, TV, and anime from a single embed. No SDK and no API key.
Multiple audio tracks — Hindi, Tamil, English and more — plus subtitles, all switchable in the player.
ready, play, pause, timeupdate, and ended posted to your page.
Play, pause, seek, and volume from the host with postMessage.
Live preview
Pick a type, type an ID, or edit the URL and load the player.
Preview runs in an iframe. Opening the same URL in a new tab won't play.
<iframe
id="vidbolt-player"
src="https://vidbolt.xyz/movie/1007757"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
allow="autoplay; encrypted-media; picture-in-picture"
></iframe>Docs
Pick a URL, paste the iframe, listen for events, send commands — or delegate mobile settings to your own bottom sheet.
Copy a URL and iframe
Do this: choose a type, copy the URL, paste the iframe on your site.
https://vidbolt.xyz/movie/{tmdb_id}Replace the curly braces with real IDs. Ready example:
https://vidbolt.xyz/movie/1007757<iframe
id="vidbolt-player"
src="https://vidbolt.xyz/movie/1007757"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
allow="autoplay; encrypted-media; picture-in-picture"
></iframe>https://vidbolt.xyz/tv/{tmdb_id}/{season}/{episode}Replace the curly braces with real IDs. Ready example:
https://vidbolt.xyz/tv/1399/1/1<iframe
id="vidbolt-player"
src="https://vidbolt.xyz/tv/1399/1/1"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
allow="autoplay; encrypted-media; picture-in-picture"
></iframe>https://vidbolt.xyz/anime/{anilist_id}/{episode}Replace the curly braces with real IDs. Ready example:
https://vidbolt.xyz/anime/16498/1<iframe
id="vidbolt-player"
src="https://vidbolt.xyz/anime/16498/1"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
allow="autoplay; encrypted-media; picture-in-picture"
></iframe>https://vidbolt.xyz/anime/mal/{mal_id}/{episode}Replace the curly braces with real IDs. Ready example:
https://vidbolt.xyz/anime/mal/53149/1<iframe
id="vidbolt-player"
src="https://vidbolt.xyz/anime/mal/53149/1"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
allow="autoplay; encrypted-media; picture-in-picture"
></iframe>Add query params
Do this: append query params to the embed URL. All optional.
https://vidbolt.xyz/movie/1007757?theme=e50914&autoPlay=true&audio=hindi| Param | What it does |
|---|---|
theme | UI accent color — hex (e50914) or CSS name (red). Defaults to white controls |
startAt | Start playback at this time in seconds |
autoPlay | Set to true to autoplay on load |
audio | Preferred audio (en, hindi, or a track name). Defaults to English when multiple tracks exist |
title | Set to false to hide the title overlay |
poster | Set to false to hide the poster / backdrop |
hideServer | Set to true to hide the server picker |
fullscreenButton | Set to false to hide fullscreen |
landscape | Phones. Set to true to turn the screen to landscape in fullscreen, even with auto-rotate off (Android; iPhone keeps its own rotation) |
nextEpisodeButton | TV / anime. Set to false to hide the Next Episode button (top right) |
episodesButton | TV / anime. Set to false to hide the Episodes button (bottom center) |
mobileSheets | Mobile iframe only. Player sends settings to your page instead of drawing them — you show a bottom sheet. See step 05 |
idType | On /anime/{id} routes, set to mal to use a MyAnimeList ID instead of AniList |
Playback events
Do this: add a message listener on your page. The iframe posts these when playback changes.
| Event | When it fires |
|---|---|
ready | Player loaded and stream manifest is ready |
play | Video started or resumed |
pause | Video paused |
timeupdate | Fires during playback — includes time in seconds |
durationchange | Total duration available — includes duration |
ended | Playback finished |
mobile-panel | Mobile sheets: user opened Settings or Subtitles — show your bottom sheet using data.options |
window.addEventListener('message', (event) => {
if (event.origin !== 'https://vidbolt.xyz') return;
const data = event.data;
if (!data || typeof data !== 'object') return;
switch (data.type) {
case 'ready': console.log('Player ready'); break;
case 'play': console.log('Playing'); break;
case 'pause': console.log('Paused'); break;
case 'timeupdate': console.log('Time:', data.time); break;
case 'durationchange': console.log('Duration:', data.duration); break;
case 'ended': console.log('Ended'); break;
}
});Play, pause, seek
Do this: post a message to the iframe. Give it id="vidbolt-player" so the helper below works.
Try it on the live player above
| Command | What it does |
|---|---|
play | Resume video playback |
pause | Pause video playback |
seek | Jump to a specific time in seconds |
volume | Set player volume from 0.0 to 1.0 |
mobile-option | Mobile sheets: user picked a row in your sheet — send the row's option and value back to apply it |
const player = document.getElementById('vidbolt-player');
function sendCommand(type, params = {}) {
player.contentWindow.postMessage({ type, ...params }, 'https://vidbolt.xyz');
}
sendCommand('play');
sendCommand('pause');
sendCommand('seek', { time: 120 });
sendCommand('volume', { volume: 0.5 });Settings on your page
Problem: settings inside a tiny iframe on mobile are hard to use.
Solution: the player sends you the options — you draw a bottom sheet on your page.
https://vidbolt.xyz/movie/1007757?theme=e50914&autoPlay=true&mobileSheets=trueWorks on mobile (≤560px), inside an iframe, with mobileSheets=true. Without a listener on your page, Settings will not open.
| Step | What to do |
|---|---|
1. Add the URL flag | Append ?mobileSheets=true to your iframe src (mobile + iframe only) |
2. Listen for mobile-panel | When the user taps Settings or CC, open your bottom sheet with data.options |
3. Reply with mobile-option | When the user picks a row, post { option, value } back to the iframe |
| Player button | Sheet opens on |
|---|---|
Subtitles button (CC) | Subtitles |
Settings button (gear) | First tab (usually Quality) |
| Tab name | Contains |
|---|---|
Quality | Video quality levels |
Subtitles | Subtitle tracks (always includes Off) |
Audio | Audio language tracks |
Servers | Streaming server list |
Playback speed | 0.5× to 2× |
Audio boost | Volume boost levels |
| option | value → result |
|---|---|
quality | -1 or index → Set HLS quality (-1 = Auto) |
sourceQuality | quality name → Switch MP4/source quality |
subtitles | -1 or index → Set subtitle track (-1 = Off) |
audio | track name → Switch audio track |
server | server id → Switch server |
speed | 1, 1.5, 2… → Set playback speed |
audioBoost | preset number → Set audio boost |
// Each item in data.options — one row in your sheet
{
option: 'subtitles', // send back in mobile-option
value: '0', // send back in mobile-option
label: 'English', // show to the user
group: 'Subtitles', // tab this row belongs to
selected: false, // true = currently active
}// Step 2: the player asks you to open a settings sheet
window.addEventListener('message', (event) => {
if (event.origin !== 'https://vidbolt.xyz') return;
if (event.data?.type !== 'mobile-panel') return;
const { options, initialGroup } = event.data;
const tabs = {};
for (const row of options) (tabs[row.group || 'Options'] ??= []).push(row);
const tabNames = Object.keys(tabs);
const activeTab = tabs[initialGroup] ? initialGroup : tabNames[0];
openBottomSheet({ tabs, tabNames, activeTab });
});// Step 3: the user tapped a row — tell the player to apply it
function onRowSelected(row) {
document.getElementById('vidbolt-player').contentWindow.postMessage(
{ type: 'mobile-option', option: row.option, value: row.value },
'https://vidbolt.xyz'
);
closeBottomSheet();
}