NEWMeet the new Video Gallery — YouTube, TikTok, Instagram Reels, Vimeo and Twitch in one widget.
Guide

YouTube IFrame API: A Practical Guide

Updated September 2026 · 19 min read

Key takeaways

  • Load https://www.youtube.com/iframe_api once and create players in onYouTubeIframeAPIReady.

  • Control playback with playVideo, pauseVideo, seekTo, mute and loadVideoById.

  • React to onStateChange and onError to track plays and skip broken videos.

  • The IFrame API needs no key; listing channel or playlist videos needs the YouTube Data API with a key and quotas.

Load the API and create a player

<div id="player"></div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>
  let player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player("player", {
      videoId: "VIDEO_ID",
      playerVars: { playsinline: 1, rel: 0 },
      events: { onReady: e => e.target.mute().playVideo() }
    });
  }
</script>

Common methods

Method
Does
playVideo() / pauseVideo()
Play and pause
seekTo(seconds)
Jump to a time
mute() / unMute()
Sound control
loadVideoById(id)
Switch videos
getCurrentTime()
Current position

playVideo() / pauseVideo()

Does

Play and pause

seekTo(seconds)

Does

Jump to a time

mute() / unMute()

Does

Sound control

loadVideoById(id)

Does

Switch videos

getCurrentTime()

Does

Current position

Events

onReady, onStateChange (playing, paused, ended), onError. Use them to track views or start the next video.

When you don’t need the API

For a gallery, playlist or channel feed on marketing pages, the API is a lot of code to maintain.

How the API loads

The IFrame API is a single script. When it finishes loading, it calls a global function named onYouTubeIframeAPIReady — create your players there. Load the script once per page, even if you have several players, and create each player on its own element.

const players = {};
function onYouTubeIframeAPIReady() {
  document.querySelectorAll("[data-yt]").forEach((el) => {
    players[el.id] = new YT.Player(el.id, {
      videoId: el.dataset.yt,
      playerVars: { rel: 0, playsinline: 1 }
    });
  });
}

Player states

Value
Constant
Meaning
-1
—
Unstarted
0
YT.PlayerState.ENDED
Ended
1
YT.PlayerState.PLAYING
Playing
2
YT.PlayerState.PAUSED
Paused
3
YT.PlayerState.BUFFERING
Buffering
5
YT.PlayerState.CUED
Video cued

-1

Constant

—

Meaning

Unstarted

0

Constant

YT.PlayerState.ENDED

Meaning

Ended

1

Constant

YT.PlayerState.PLAYING

Meaning

Playing

2

Constant

YT.PlayerState.PAUSED

Meaning

Paused

3

Constant

YT.PlayerState.BUFFERING

Meaning

Buffering

5

Constant

YT.PlayerState.CUED

Meaning

Video cued

Listen to onStateChange and compare event.data with these constants.

Build a custom play button

<div id="player"></div>
<button id="play">Play</button>
<script>
  let player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player("player", { videoId: "VIDEO_ID", playerVars: { controls: 0 } });
  }
  document.getElementById("play").onclick = () => {
    const s = player.getPlayerState();
    s === YT.PlayerState.PLAYING ? player.pauseVideo() : player.playVideo();
  };
</script>

Hiding YouTube’s controls means you take responsibility for accessible controls — keyboard support and labels.

Track plays and completions

events: {
  onStateChange: (e) => {
    const title = e.target.getVideoData().title;
    if (e.data === YT.PlayerState.PLAYING) gtag("event", "video_start", { video_title: title });
    if (e.data === YT.PlayerState.ENDED)   gtag("event", "video_complete", { video_title: title });
  }
}

Handle errors

Code
Meaning
What to do
2
Invalid parameter (often a wrong video ID)
Check the ID
5
HTML5 player error
Retry or show a fallback
100
Video not found or private
Remove it from the list
101 / 150
Owner doesn’t allow embedding
Link to YouTube instead

2

Meaning

Invalid parameter (often a wrong video ID)

What to do

Check the ID

5

Meaning

HTML5 player error

What to do

Retry or show a fallback

100

Meaning

Video not found or private

What to do

Remove it from the list

101 / 150

Meaning

Owner doesn’t allow embedding

What to do

Link to YouTube instead

Listen to onError and skip to the next video in your list when an error occurs.

IFrame API vs. YouTube Data API

The IFrame API controls playback of videos you already know. To list a channel’s uploads or a playlist’s videos, you need the separate YouTube Data API — with an API key, daily quota limits and caching on your side. That’s the part most custom galleries underestimate.

A complete example: a playlist of product videos

A common use case: one player, a list of your product videos next to it, and analytics for each play. Create the player once, render your list as buttons with data-id attributes, and call loadVideoById on click. On ENDED, load the next ID in your list so the playlist continues. Send video_start and video_complete events to analytics with the video title. Everything else — thumbnails, titles, the order of videos — comes from your own data, which is exactly the part the Data API or a gallery widget provides.

Frequently asked questions

Official documentation

Related

YouTube Video Player for Your Website

Embed a YouTube player on your website that looks like part of your site — with a gallery or playlist of more videos.YouTube Video Player for Your Website