# Autoplay

Start playback automatically and handle browser autoplay restrictions.

For the best chance of autoplay succeeding, start playback muted and enable inline playback. Autoplay is a request, not a guarantee: browsers can block it based on audio state, prior interaction with your site, browser settings, and platform policy.

## Recommended approach

Set autoplay, muted, and inline playback on the media element, and keep a manual play control available for when autoplay is blocked.

**index.html**

```html
<video-player class="video-player">
  <media-container>
    <video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" autoplay muted playsinline></video>
    <media-play-button class="media-play-button">
      <span class="paused">Play</span>
      <span class="playing">Pause</span>
      <span class="ended">Replay</span>
    </media-play-button>
  </media-container>
</video-player>
```

**index.css**

```css
.video-player {
  position: relative;
}

.video-player video {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.media-play-button {
  position: absolute;
  bottom: 10px;
  left: 10px;
  padding-block: 8px;
  padding-inline: 20px;
  color: black;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 9999px;
  backdrop-filter: blur(10px);
}

.media-play-button .paused {
  display: none;
}
.media-play-button .playing {
  display: none;
}
.media-play-button .ended {
  display: none;
}
.media-play-button[data-paused]:not([data-ended]) .paused {
  display: inline;
}
.media-play-button:not([data-paused]) .playing {
  display: inline;
}
.media-play-button[data-ended] .ended {
  display: inline;
}
.media-play-button[data-ended] .paused {
  display: none;
}
.media-play-button[data-ended] .playing {
  display: none;
}
```

**index.ts**

```ts
import '@videojs/html/video/player';
import '@videojs/html/ui/container';
import '@videojs/html/ui/play-button';
```

## How it works

The `autoplay`, `muted`, and `playsinline` attributes on `<video>` and similar media components pass through to the underlying media element. When the media element supports them, they’re applied, and playback is requested as soon as the media has enough data.

The [playback feature](https://videojs.org/docs/framework/html/reference/api/feature-playback) reflects the result in player state. When autoplay succeeds, `paused` becomes `false` and `started` becomes `true`. When the browser blocks autoplay, the player stays `paused: true` with `started: false`, and the [Play button](https://videojs.org/docs/framework/html/reference/components/play-button) renders its play state. There is no separate autoplay failure event: a blocked autoplay looks like media that never started.

Calling `play()` from player state returns the native promise from the media element. When the browser blocks playback, that promise rejects with a `NotAllowedError`.

## Availability and constraints

- Autoplay can fail. Browsers decide per page load based on audio state, whether the user has interacted with your site before, browser settings, and platform policy.
- Muted autoplay is broadly allowed. Unmuted autoplay is blocked on first visit in most browsers; do not rely on it.
- Without inline playback, iPhone Safari opens the video in fullscreen when playback starts.
- Low-power mode and data-saver settings can block even muted autoplay. This is why the recommended approach keeps a manual play control.
- Programmatic volume control is unsupported on some platforms. The [volume feature](https://videojs.org/docs/framework/html/reference/api/feature-volume) exposes this as `volumeAvailability: 'available' | 'unavailable' | 'unsupported'`; iOS Safari reports `'unsupported'`, and `'unavailable'` means the feature hasn’t attached to a media element yet.
- This guide applies to media components that render a video element (`<video>`, `<hlsjs-video>`, `<dash-video>`, `<mux-video>`, and the like). Embed components (YouTube, Vimeo, TikTok, Twitch) forward autoplay to the third-party player, which applies its own autoplay rules; muted and inline behavior varies by provider.

## Common variations

### Background video

Background video autoplays, loops, stays muted, and omits interactive controls. Use `<hls-background-video>` instead of configuring these behaviors yourself: it applies them by default and streams an HLS source, picking one rendition that fits the screen for the whole session.

Install the SPF adapter with the HTML façade:

```bash
pnpm add @videojs/html @videojs/spf
```

```html
<hls-background-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></hls-background-video>
<script type="module">
  import '@videojs/html/media/hls-background-video';
</script>
```

If you have a progressive MP4 or WebM file instead of an HLS stream, `<background-video>` is the same component without the streaming engine. See [`<background-video>`](https://videojs.org/docs/framework/html/reference/components/background-video) for opt-out attributes and sizing.

### Autoplay with sound

Do not rely on unmuted autoplay for a user’s first visit. Start playback from an explicit user action instead.

Call `play()` on the media element from a click handler:

```html
<video-player>
  <media-container>
    <video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
  </media-container>
</video-player>
<button type="button" id="start">Play video</button>
<script type="module">
  import '@videojs/html/video/player';

  document.querySelector('#start').addEventListener('click', () => {
    document.querySelector('video').play();
  });
</script>
```

Because playback starts from a user gesture, the browser allows it unmuted.

## Troubleshooting

### Playback does not start

Confirm that:

- The media is muted.
- Inline playback is enabled.
- The source loads (check the network panel).
- A manual play control is available as a fallback.

If autoplay is blocked, the player stays paused and the Play button remains in its play state; there is no error state to handle.

### The video opens fullscreen on iPhone

Enable inline playback with the `playsinline` attribute on the media element.

### The video starts without sound

Expected with muted autoplay. Let the user unmute through a [Mute button](https://videojs.org/docs/framework/html/reference/components/mute-button) or [Volume slider](https://videojs.org/docs/framework/html/reference/components/volume-slider) rather than unmuting programmatically; programmatic volume changes are unsupported on some platforms.

## Related pages

### Components

- [media-play-button](https://videojs.org/docs/framework/html/reference/components/play-button): Accessible play/pause button with keyboard support and customizable rendering
- [media-mute-button](https://videojs.org/docs/framework/html/reference/components/mute-button): Accessible mute/unmute button with keyboard support and volume state reflection
- [background-video](https://videojs.org/docs/framework/html/reference/components/background-video): Decorative background video element with automatic muting and looping
- [media-controls](https://videojs.org/docs/framework/html/reference/components/controls): Container component for composing and auto-hiding video player controls on user interaction

### API

- [Playback](https://videojs.org/docs/framework/html/reference/api/feature-playback): Play/pause state and actions for the player store
- [Volume](https://videojs.org/docs/framework/html/reference/api/feature-volume): Volume level and mute state for the player store
- [PlayerController](https://videojs.org/docs/framework/html/reference/api/player-controller): Reactive controller for accessing player store state in HTML custom elements

### Guides

- [Features](https://videojs.org/docs/framework/html/guides/features): The state and actions each feature adds to the player
- [Browser support](https://videojs.org/docs/framework/html/guides/browser-support): Browsers and rendering environments supported by Video.js 10, and what the stylesheets need from them

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
