---
title: "YouTube Player · Nuxt Scripts"
meta:
  description: "Nuxt Scripts lets you load third-party scripts with better performance, privacy, security and DX. It includes many popular third-parties out of the box."
  "og:description": "Nuxt Scripts lets you load third-party scripts with better performance, privacy, security and DX. It includes many popular third-parties out of the box."
  "og:title": "YouTube Player · Nuxt Scripts"
---

```

Nuxt Scripts on GitHub

**Scripts**# **YouTube Player**[Copy for LLMs](https://scripts.nuxt.com/scripts/youtube-player.md) [**~~YouTube~~**](https://youtube.com/) is a video hosting platform that allows you to upload and share videos. Nuxt Scripts provides a [`useScriptYouTubePlayer()`](https://scripts.nuxt.com/scripts/youtube-player) composable and a headless [`<ScriptYouTubePlayer>`](https://scripts.nuxt.com/scripts/youtube-player) component to interact with the YouTube Player.**YouTube Player**[**~~View source ~~**](https://github.com/nuxt/scripts/blob/main/packages/script/src/runtime/registry/youtube-player.ts) ## Nuxt Config Setup Add this to your `nuxt.config.ts` to load YouTube Player globally. Alternatively you can use the **~~useScriptYouTubePlayer~~** composable for more control.```
export default defineNuxtConfig({
  scripts: {
    registry: {
      youtubePlayer: {
        trigger: 'onNuxtReady',
      }
    }
  }
})
``` This config automatically enables **~~first-party mode ~~** (bundle + proxy). See below to customise. ## useScriptYouTubePlayer() The `useScriptYouTubePlayer` composable lets you have fine-grain control over when and how YouTube Player is loaded on your site.```
const { proxy } = useScriptYouTubePlayer()

const { YT } = await proxy
``` Please follow the [**~~Registry Scripts ~~**](https://scripts.nuxt.com/docs/guides/registry-scripts) guide to learn more about advanced usage. ## First-Party Mode: Privacy Focused Proxy No extra config needed. The script is bundled from your domain (faster loads, no extra DNS lookup) and runtime requests are reverse-proxied through your server with automatic anonymisation (user IPs stay hidden from YouTube Player, works with ad blockers). [**~~Learn more. ~~**](https://scripts.nuxt.com/docs/guides/first-party)**Mode**Bundle Proxy**Privacy**User IP addresses are anonymised. Other request data passes through.```
export default defineNuxtConfig({
  scripts: {
    // ✅ First-party mode: bundled + proxied
    registry: {
      youtubePlayer: {
        trigger: 'onNuxtReady',
      },
    },
  },
})
```## Example Using YouTube Player in a component with the proxy to send events .```
<script setup lang="ts">
const { proxy } = useScriptYouTubePlayer()

// noop in development, ssr
// just works in production, client
function handleAction() {
  const { YT } = await proxy
}
</script>

<template>
  <div>
    <button @click="handleAction">
      Send Event
    </button>
  </div>
</template>
```## Types To use [**~~YouTube~~**](https://youtube.com) with full TypeScript support, you will need to install the `@types/youtube` dependency.```
pnpm add -D @types/youtube
```## [`<ScriptYouTubePlayer>`](https://scripts.nuxt.com/scripts/youtube-player) The [`<ScriptYouTubePlayer>`](https://scripts.nuxt.com/scripts/youtube-player) component is a wrapper around the [`useScriptYouTubePlayer()`](https://scripts.nuxt.com/scripts/youtube-player) composable. It provides a simple way to embed YouTube videos in your Nuxt app. It's optimized for performance by using the [**~~Element Event Triggers~~**](https://scripts.nuxt.com/docs/guides/script-triggers#element-event-triggers), only loading the YouTube Player when the specific elements events happen. By default, it will load on the `mousedown` event. ### Demo**Click to load** Clicking the video will load the YouTube iframe and start the video.```
<script setup lang="ts">
const isLoaded = ref(false)
const isPlaying = ref(false)
const video = ref()
async function play() {
  await video.value.player.playVideo()
}
function stateChange(event) {
  isPlaying.value = event.data === 1
}
</script>

<template>
  <div>
    <div class="flex items-center justify-center p-5">
      <ScriptYouTubePlayer ref="video" video-id="d_IFKP1Ofq0" @ready="isLoaded = true" @state-change="stateChange">
        <template #awaitingLoad>
          <div class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 h-[48px] w-[68px]">
            <svg height="100%" version="1.1" viewBox="0 0 68 48" width="100%"><path d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f00" /><path d="M 45,24 27,14 27,34" fill="#fff" /></svg>
          </div>
        </template>
      </ScriptYouTubePlayer>
    </div>
    <div class="text-center">
      <UAlert v-if="!isLoaded" class="mb-5" size="sm" color="blue" variant="soft" title="Click to load" description="Clicking the video will load the Youtube iframe and start the video." />
      <UButton v-if="isLoaded && !isPlaying" @click="play">
        Play Video
      </UButton>
    </div>
  </div>
</template>
```### Privacy The `<ScriptYouTubePlayer>` component is privacy-friendly by default and sets the video host to `https://www.youtube-nocookie.com`. To modify this behavior, you can set the `host` prop to `https://www.youtube.com`.```
<ScriptYouTubePlayer video-id="d_IFKP1Ofq0" :player-options="{ host: 'https://www.youtube.com' }" />
```### Placeholder The YouTube Player placeholder image is 1280x720 webp that is lazy-loaded by default. To modify the placeholder size you can set the `thumbnailSize` prop, if you'd prefer to use a `jpg` you can pass the `webp` prop as `false`.```
<ScriptYouTubePlayer video-id="d_IFKP1Ofq0" thumbnail-size="maxresdefault" />
``` If you need fine control over the placeholder you can set `placeholderAttrs` prop or override it using the `#placeholder` slot. #### Eager Loading You should change this behavior if your video is above the fold or consider using the `#placeholder` slot to customize the placeholder image.```
<ScriptYouTubePlayer above-the-fold />
``````
<ScriptYouTubePlayer>
  <template #placeholder="{ placeholder }">
    <img :src="placeholder" alt="Video Placeholder">
  </template>
</ScriptYouTubePlayer>
```### Component API See the [**~~Facade Component API~~**](https://scripts.nuxt.com/docs/guides/facade-components#facade-components-api) for full props, events, and slots. ### Events The [`<ScriptYouTubePlayer>`](https://scripts.nuxt.com/scripts/youtube-player) component emits all events from the YouTube Player SDK. Please consult the [**~~Player Events~~**](https://developers.google.com/youtube/iframe_api_reference#Events) for full documentation.```
const emits = defineEmits<{
  'ready': [e: YT.PlayerEvent]
  'state-change': [e: YT.OnStateChangeEvent, target: YT.Player]
  'playback-quality-change': [e: YT.OnPlaybackQualityChangeEvent, target: YT.Player]
  'playback-rate-change': [e: YT.OnPlaybackRateChangeEvent, target: YT.Player]
  'error': [e: YT.OnErrorEvent, target: YT.Player]
  'api-change': [e: YT.PlayerEvent, target: YT.Player]
}>()
```### Slots As Nuxt provides the component headless, you can use slots to customize the player however you like before it loads.**default** The default slot displays content that will always be visible.```
<template>
  <ScriptYouTubePlayer video-id="d_IFKP1Ofq0">
    <div class="bg-blue-500 text-white p-5">
      Video by Nuxt
    </div>
  </ScriptYouTubePlayer>
</template>
```**awaitingLoad** This slot displays content while the video is loading.```
<template>
  <ScriptYouTubePlayer video-id="d_IFKP1Ofq0">
    <template #awaitingLoad>
      <div class="bg-blue-500 text-white p-5">
        Click to play!
      </div>
    </template>
  </ScriptYouTubePlayer>
</template>
```**loading** This slot displays content while the video is loading.```
<template>
  <ScriptYouTubePlayer video-id="d_IFKP1Ofq0">
    <template #loading>
      <div class="bg-blue-500 text-white p-5">
        Loading...
      </div>
    </template>
  </ScriptYouTubePlayer>
</template>
```**placeholder** This slot displays a placeholder image before the video loads. By default, this will show the YouTube thumbnail for the video. You can display it however you like.```
<template>
  <ScriptYouTubePlayer video-id="d_IFKP1Ofq0">
    <template #placeholder="{ placeholder }">
      <img :src="placeholder" alt="Video Placeholder">
    </template>
  </ScriptYouTubePlayer>
</template>
```## [`useScriptYouTubePlayer()`](https://scripts.nuxt.com/scripts/youtube-player) The [`useScriptYouTubePlayer()`](https://scripts.nuxt.com/scripts/youtube-player) composable lets you have fine-grain control over the YouTube Player SDK. It provides a way to load the YouTube Player SDK and interact with it programmatically.```
export function useScriptYouTubePlayer<T extends YouTubePlayerApi>(_options: YouTubePlayerInput) {}
``` Please follow the [**~~Registry Scripts~~**](https://scripts.nuxt.com/docs/guides/registry-scripts) guide to learn more about advanced usage.```
export interface YouTubePlayerApi {
  YT: MaybePromise<{
    Player: YT.Player
    PlayerState: YT.PlayerState
    get: (k: string) => any
    loaded: 0 | 1
    loading: 0 | 1
    ready: (f: () => void) => void
    scan: () => void
    setConfig: (config: YT.PlayerOptions) => void
    subscribe: <EventName extends keyof YT.Events>(
      event: EventName,
      listener: YT.Events[EventName],
      context?: any,
    ) => void
    unsubscribe: <EventName extends keyof YT.Events>(
      event: EventName,
      listener: YT.Events[EventName],
      context?: any,
    ) => void
  }>
}
```## Example Loading the YouTube Player SDK and interacting with it programmatically.```
<script setup lang="ts">
const video = ref()
const { onLoaded } = useScriptYouTubePlayer()

const player = ref(null)
onLoaded(async ({ YT }) => {
  // we need to wait for the internal YouTube APIs to be ready
  const YouTube = await YT
  await new Promise<void>((resolve) => {
    if (typeof YT.Player === 'undefined')
      YouTube.ready(resolve)
    else
      resolve()
  })
  // load the API
  player.value = new YT.Player(video.value, {
    videoId: 'd_IFKP1Ofq0'
  })
})
function play() {
  player.value?.playVideo()
}
</script>

<template>
  <div>
    <div ref="video" />
    <button @click="play">
      Play
    </button>
  </div>
</template>
```[~~Edit this page~~](https://github.com/nuxt/scripts/edit/main/docs/content/scripts/youtube-player.md) [~~Markdown For LLMs~~](https://scripts.nuxt.com/scripts/youtube-player.md) [**X Pixel** Use X Pixel in your Nuxt app.](https://scripts.nuxt.com/scripts/x-pixel) **On this page **- [Types](#types) - [<ScriptYouTubePlayer>](#scriptyoutubeplayer) - [useScriptYouTubePlayer()](#usescriptyoutubeplayer) - [Example](#example)