Skip navigation

IFrame Player API

Updated: 28.04.2026
Open as Markdown

IFrame Player API allows programmatic player control via JavaScript: start and stop playback, manage volume, subscribe to events, and much more.

Who this article is for

  • Frontend developers — need to programmatically control the player on the page
  • LMS developers — need to track learning progress and create interactive scenarios
  • Application developers — need to integrate the player with application business logic

Why use IFrame Player API?

With IFrame Player API you can:

  • Programmatically control the player — start, stop, seek video
  • React to events — track playback start, pauses, video end
  • Create interactive scenarios — synchronize the player with other page elements
  • Manage playlists — dynamically switch between videos
  • Configure parameters — change quality, volume, playback speed programmatically

What IFrame Player API offers

IFrame Player API helps connect the player to your application logic: control playback and subscribe to events.

Control and events

  • Integration with application logic — you can tie player control to user state, access rights, and other conditions in your product.
  • Promise interface — API methods return a Promise, so they’re convenient to call via await or .then().
  • Player events — subscribing to events (play/pause/ended, etc.) lets you trigger actions in your interface at the right moment.

Custom metrics and data sending

  • Analytics context — you can enrich events with your own data (e.g., user ID, course, lesson, device, browser).
  • Detailed events — when needed, track pauses, seeks, replays, and other actions.
  • Export to your systems — send collected events to your analytics, CRM, or LMS.

Parameters and scenarios

  • Change parameters on the fly — change volume, speed, quality, and other settings when contextually appropriate.
  • Scenarios over video — create interactive mechanics (quizzes, transitions, hints) tied to player events.

Typical use cases

Learning Management Systems (LMS)

IFrame Player API is especially useful for educational platforms where many factors matter:

  • Tracking learning progress — recording watch time, lesson completion, replays
  • Adaptive learning — automatically advancing to the next lesson after the current one ends
  • Knowledge checks — pausing playback to show questions at specific moments
  • Personalization — configuring playback speed, video quality, and other parameters to student preferences
  • Grade system integration — linking video viewing to grades and achievements

Interactive applications

  • Content synchronization — showing additional information, comments, or subtitles at specific video moments
  • Form integration — pausing playback to fill in forms or complete surveys
  • Multi-screen scenarios — controlling multiple players on one page

Corporate portals

  • Access control — checking user permissions before playback
  • Activity logging — detailed tracking of content usage by employees
  • Internal system integration — linking video viewing to tasks, projects, and reports

Example: Advanced analytics for learning systems

Here’s an example of building an analytics system that collects video view data and enriches it with context:

// Analytics system for an educational platform
class LearningAnalytics {
  constructor(player, context) {
    this.player = player;
    this.context = {
      userId: context.userId,
      courseId: context.courseId,
      lessonId: context.lessonId,
      device: this.getDeviceInfo(),
      browser: this.getBrowserInfo(),
      timestamp: new Date().toISOString()
    };
    this.events = [];
    this.setupEventListeners();
  }

  setupEventListeners() {
    const player = this.player;

    // Track playback start
    player.on(player.Events.Play, () => {
      this.trackEvent('play', {
        currentTime: null, // will get on next TimeUpdate
        playbackRate: null
      });
    });

    // Track pause
    player.on(player.Events.Pause, async () => {
      const currentTime = await player.getCurrentTime();
      const duration = await player.getDuration();
      const percent = (currentTime / duration) * 100;

      this.trackEvent('pause', {
        currentTime,
        percent,
        reason: this.detectPauseReason() // e.g., "user_action", "network_issue"
      });
    });

    // Track view progress
    let lastTrackedPercent = 0;
    player.on(player.Events.TimeUpdate, async (event) => {
      const percent = event.data.percent;
      
      // Send event every 10% viewed
      if (percent - lastTrackedPercent >= 10) {
        lastTrackedPercent = percent;
        this.trackEvent('progress', {
          percent: Math.floor(percent),
          currentTime: event.data.currentTime
        });
      }
    });

    // Track playback end
    player.on(player.Events.Ended, async () => {
      const duration = await player.getDuration();
      this.trackEvent('completed', {
        totalDuration: duration,
        watchedDuration: duration // can be computed from pause events
      });
    });

    // Track seeking
    let lastSeekTime = 0;
    player.on(player.Events.Seeked, async () => {
      const currentTime = await player.getCurrentTime();
      if (Math.abs(currentTime - lastSeekTime) > 5) {
        this.trackEvent('seek', {
          from: lastSeekTime,
          to: currentTime,
          direction: currentTime > lastSeekTime ? 'forward' : 'backward'
        });
      }
      lastSeekTime = currentTime;
    });

    // Track quality changes
    player.on(player.Events.QualityChanged, (event) => {
      this.trackEvent('quality_changed', {
        quality: event.data.quality,
        reason: 'user_selection' // or 'auto_adaptation'
      });
    });

    // Track errors
    player.on(player.Events.Error, (event) => {
      this.trackEvent('error', {
        error: event.data.error,
        currentTime: null // can be fetched asynchronously
      });
    });
  }

  trackEvent(eventType, eventData) {
    const event = {
      type: eventType,
      data: eventData,
      context: this.context,
      timestamp: new Date().toISOString()
    };

    this.events.push(event);
    
    // Send event to your analytics system
    this.sendToAnalytics(event);
  }

  async sendToAnalytics(event) {
    try {
      await fetch('/api/analytics/track', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(event)
      });
    } catch (error) {
      console.error('Analytics send error:', error);
      // Can save to local storage for retry
    }
  }

  detectPauseReason() {
    // Logic to determine pause reason
    return 'user_action';
  }

  getDeviceInfo() {
    return {
      type: /Mobile|Android|iPhone|iPad/.test(navigator.userAgent) ? 'mobile' : 'desktop',
      screen: {
        width: window.screen.width,
        height: window.screen.height
      }
    };
  }

  getBrowserInfo() {
    return {
      name: navigator.userAgent.match(/(Chrome|Firefox|Safari|Edge)\/[\d.]+/)?.[1] || 'unknown',
      version: navigator.userAgent.match(/(Chrome|Firefox|Safari|Edge)\/([\d.]+)/)?.[2] || 'unknown'
    };
  }

  getSummary() {
    return {
      totalEvents: this.events.length,
      events: this.events,
      context: this.context
    };
  }
}

// Using the analytics system
function onKinescopeIframeAPIReady(playerFactory) {
  playerFactory
    .create('player', {
      url: 'https://kinescope.io/1111111',
      size: { width: '100%', height: 400 }
    })
    .then(function (player) {
      // Initialize analytics system with learning context
      const analytics = new LearningAnalytics(player, {
        userId: 'user_12345',
        courseId: 'course_67890',
        lessonId: 'lesson_11111',
      });

      // Example: send summary on page close
      window.addEventListener('beforeunload', () => {
        const summary = analytics.getSummary();
        navigator.sendBeacon('/api/analytics/track', JSON.stringify({
          type: 'session_end',
          summary: summary
        }));
      });
    });
}

This example shows how to:

  • Collect detailed data about video views tied to the learning context
  • Enrich events with user, course, device, and other information
  • Track various metrics — watch time, pauses, seeks, video quality
  • Integrate with your system — sending data to your analytics, LMS, or other systems

Integrating with application logic

IFrame Player API makes it easy to integrate the player with your application’s internal logic:

Example: Access control

function onKinescopeIframeAPIReady(playerFactory) {
  checkUserAccess()
    .then(hasAccess => {
      if (!hasAccess) {
        showAccessDeniedMessage();
        return;
      }

      return playerFactory.create('player', {
        url: 'https://kinescope.io/1111111',
        size: { width: '100%', height: 400 }
      });
    })
    .then(function (player) {
      if (!player) return;
      setupPlayerLogic(player);
    });
}

async function checkUserAccess() {
  const response = await fetch('/api/check-access');
  const data = await response.json();
  return data.hasAccess;
}

function setupPlayerLogic(player) {
  player.on(player.Events.Ended, async () => {
    await updateUserProgress();
    await unlockNextLesson();
    showNotification('Lesson complete!');
  });
}

Example: Synchronizing with application state

// Integration with React/Vue/Angular application state
function createPlayerWithState(playerFactory, appState) {
  return playerFactory.create('player', {
    url: appState.currentVideo.url,
    behavior: {
      autoPlay: appState.settings.autoPlay,
      muted: appState.settings.muted
    }
  }).then(function (player) {
    player.on(player.Events.Pause, () => {
      appState.setPlayerState('paused');
    });

    player.on(player.Events.Playing, () => {
      appState.setPlayerState('playing');
    });

    appState.on('videoChanged', (newVideo) => {
      player.switchTo(newVideo.id);
    });

    return player;
  });
}

Connecting the API

To use IFrame Player API, include the script on the page and declare the onKinescopeIframeAPIReady function, which will be called automatically after the API loads.

Basic connection example

<!doctype html>
<html>
  <body>
    <!-- Player container -->
    <div id="player"></div>

    <script>
      // Load the IFrame Player API script
      var tag = document.createElement('script');
      tag.src = 'https://player.kinescope.io/latest/iframe.player.js';
      var firstScriptTag = document.getElementsByTagName('script')[0];
      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

      // This function is called automatically after the API loads
      function onKinescopeIframeAPIReady(playerFactory) {
        playerFactory
          .create('player', {
            url: 'https://kinescope.io/1111111',
            size: { width: '100%', height: 400 },
          })
          .then(function (player) {
            console.log('Player created:', player);
          });
      }
    </script>
  </body>
</html>

Creating a player

Use the create method of the playerFactory object to create a player:

playerFactory.create(elementId, options).then(function(player) {
  // Player is ready
});

Creation parameters

  • elementId — ID of the page element to be replaced with an iframe (or ID of an existing iframe)
  • options — player settings object

Main parameters

{
  // Video URL (required)
  url: 'https://kinescope.io/1111111',
  
  // Player dimensions
  size: {
    width: '100%',  // or number in pixels
    height: 400     // or string '56.25%' for 16:9 ratio
  },
  
  // Behavior settings
  behavior: {
    preload: 'metadata',  // 'none', 'metadata', 'auto'
    autoPlay: false,
    muted: false,
    loop: false,
    keyboard: true,
    playsInline: true
  },
  
  // UI settings
  ui: {
    language: 'en',
    controls: true,
    mainPlayButton: true
  }
}

Example: Creating a player with settings

function onKinescopeIframeAPIReady(playerFactory) {
  playerFactory
    .create('player', {
      url: 'https://kinescope.io/1111111',
      size: {
        width: '100%',
        height: '56.25%'  // 16:9 ratio
      },
      behavior: {
        preload: 'metadata',
        autoPlay: false,
        muted: false
      },
      ui: {
        language: 'en',
        controls: true
      }
    })
    .then(function (player) {
      console.log('Player ready');
    });
}

Player control

After creating the player you receive a player object with methods for controlling playback.

Main control methods

Playback

await player.play();
await player.pause();
await player.stop();
await player.seekTo(60);  // seek to 1 minute

Getting information

const isPaused = await player.isPaused();
const isEnded = await player.isEnded();
const currentTime = await player.getCurrentTime();
const duration = await player.getDuration();

Volume control

const volume = await player.getVolume();
await player.setVolume(0.5);  // set 50%
await player.mute();
await player.unmute();
const isMuted = await player.isMuted();

CTA control

await player.closeCTA();

Quality control

const qualities = await player.getVideoQualityList();
const currentQuality = await player.getVideoQuality();
await player.setVideoQuality('1080p');

Playback speed control

const playbackRate = await player.getPlaybackRate();
await player.setPlaybackRate(1.5);  // 1.5x speed

Fullscreen mode

const isFullscreen = await player.isFullscreen();
await player.setFullscreen(true);

Picture-in-picture mode

const isPip = await player.isPip();
await player.setPip(true);

Example: Using methods

function onKinescopeIframeAPIReady(playerFactory) {
  playerFactory
    .create('player', {
      url: 'https://kinescope.io/1111111',
      size: { width: '100%', height: 400 }
    })
    .then(function (player) {
      player.setVolume(0.5);
      
      player.on(player.Events.Playing, function() {
        console.log('Playback started');
      });
      
      player.on(player.Events.Pause, function() {
        console.log('Playback paused');
      });
      
      player.on(player.Events.TimeUpdate, function(event) {
        console.log('Current time:', event.data.currentTime);
      });
    });
}

Player events

The player fires events you can subscribe to for tracking state changes.

Subscribing to events

player.on(player.Events.Play, function(event) {
  console.log('Playback started');
});

player.once(player.Events.Loaded, function(event) {
  console.log('Player loaded');
});

function handler(event) {
  console.log('Event occurred');
}
player.on(player.Events.Play, handler);
player.off(player.Events.Play, handler);

Main events

  • Events.Loaded — player has loaded all necessary data and is ready to play
  • Events.Play — playback started
  • Events.Playing — playback is active
  • Events.Pause — pause
  • Events.Ended — playback ended
  • Events.TimeUpdate — current playback time changed
  • Events.VolumeChange — volume level changed
  • Events.QualityChanged — video quality changed
  • Events.FullscreenChange — fullscreen mode changed
  • Events.CallAction — CTA button clicked
  • Events.Error — critical error

Event data

Each event contains a data object:

{
  type: player.Events.Play,
  data: { /* event data */ },
  target: player
}

Example: Working with events

player
  .once(player.Events.Loaded, function(event) {
    console.log('Duration:', event.data.duration);
    console.log('Quality:', event.data.quality);
  })
  .on(player.Events.TimeUpdate, function(event) {
    const currentTime = event.data.currentTime;
    const percent = event.data.percent;
    console.log(`Played: ${currentTime}s (${percent}%)`);
  })
  .on(player.Events.Ended, function() {
    console.log('Playback finished');
  })
  .on(player.Events.Error, function(event) {
    console.error('Player error:', event.data.error);
  });

Working with playlists

IFrame Player API supports creating and managing playlists of multiple videos.

Creating a playlist

playerFactory
  .create('player', {
    url: 'https://kinescope.io/1111111',
    playlist: [
      {
        id: 'video1',
        title: 'First Video',
        subtitle: 'Description of the first video'
      },
      {
        id: 'video2',
        title: 'Second Video',
        subtitle: 'Description of the second video'
      }
    ],
    behavior: {
      playlist: {
        autoSwitch: true,
        loop: false
      }
    }
  })
  .then(function(player) {
    // Player with playlist is ready
  });

Playlist control

const currentItem = await player.getPlaylistItem();

await player.switchTo('video2', {
  autoPlay: true,
  time: 0
});

await player.next();
await player.previous();

player.on(player.Events.CurrentTrackChanged, function(event) {
  console.log('Current video:', event.data.item.id);
});

Call To Action (CTA)

Beta feature. May change after collecting feedback.

Call To Action (CTA) allows you to show calls to action during video playback. Useful for ads, subscriptions, registrations, or other goals.

How it works: When CTA activates, playback stops and an action screen is shown over the player. When the user clicks the action button, an event fires that you can handle programmatically.

CTA can be configured to show:

  • At the end of a video or playlist
  • At specific playback moments
  • When the video is paused

Configuring CTA via IFrame API

Use the playlist parameter when creating the player. See the full documentation for all API capabilities.

CTA configuration example:

import { createPlayer } from '@kinescope/iframe-api';

const player = await createPlayer({
  videoId: '123456789',
  playlist: [
    {
      videoId: '123456789',
      cta: {
        title: 'Subscribe to our channel',
        description: 'Get new videos first',
        buttonText: 'Subscribe',
        buttonUrl: 'https://example.com/subscribe',
        showAt: 'end' // or time in seconds
      }
    }
  ]
});

Programmatic CTA control

To close the CTA screen programmatically, call the closeCTA() method on the player object:

await player.closeCTA();

Handling CTA events

When the user clicks the CTA button, the CallAction event fires. Subscribe to track interactions:

player.on(player.Events.CallAction, function(event) {
  console.log('CTA clicked:', event.data);
});

See the full IFrame Player Factory documentation for all creation parameters, and the events documentation for player events.

TypeScript types

A library with TypeScript types is available:

npm install @kinescope/player-iframe-api-loader

See more about the library and types on GitHub .

Recommendations

  • Don’t store the player object in a global variable — this can create security issues
  • Use await or .then() — all API methods return a Promise
  • Unsubscribe from events — when removing the player, remember to unsubscribe from all events
  • Handle errors — subscribe to Events.Error to handle critical errors

Full documentation

For complete information about all API methods, events, and parameters, see the full IFrame Player API documentation .

What’s next?

  1. Analytics — collect metrics and link them to your context (user, course, lesson, etc.)
  2. Player customization — customize player appearance and behavior
  3. Embedding — basic player embedding without API
  4. Troubleshooting — common API issues

Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!