<video autoplay> Considered Harmful
Published: 2020-01-23 17:19:28

If you’re trying to autoplay videos on the web, you might be tempted to reach for the [HTML5 autoplay attribute](https://www.w3schools.com/tags/att_video_autoplay.asp). This sounds exactly like what you’re looking for, right? Well, not exactly. Let’s talk about why that’s probably not what you’re looking for and what the better option is.

## Browsers will block your autoplay attempts

Over the last few years, all major browser vendors have taken steps to aggressively block autoplaying videos on webpages. Safari announced some policy changes in [June 2017](https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/) and [Chrome followed suit](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes) shortly after [and Firefox after that](https://support.mozilla.org/en-US/kb/block-autoplay).


> In summary: all these browsers will aggressively block videos from autoplaying on webpages. Each browser has slightly different rules around how it makes this decision. It’s a huge black box and browsers will not tell you what their exact rules are. The default behavior is block most autoplay attempts.

There are however some conditions that make it more likely for autoplay to work:

  * Your video is muted with the muted attribute.
  * The user has interacted with the page with a click or a tap.
  * (Chrome - desktop) The user’s [Media Engagement Index](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#mei) threshold has been crossed. Chrome keeps track of how often a user consumes media on a site and if a user has played a lot of media on this site then Chrome will probably allow autoplay.
  * (Chrome - mobile) The user has added the site to their home screen.
  * (Safari) Device is not in power-saving mode.

These conditions only make autoplay more likely, but remember that aside from these conditions, the user can override the browser’s default setting on a per-domain basis. This basically means that you can never rely on autoplay actually working.

## Autoplay will probably work for you, but it will break for your users

Even if you try to follow the rules above, autoplay is still a finicky beast. One thing to keep in mind (for Chrome at least) is that due to Chrome’s Media Engagement Index. When you are testing autoplay on your own site it will probably work for you (because you visit your site often and play content, your MEI score is high). But then when new users come to your site, it is likely to fail (because their MEI score is low). As a developer, this is incredibly frustrating and another reason to always avoid the autoplay attribute.

![works on my machine](https://thepracticaldev.s3.amazonaws.com/i/3453zr9gg72dikggiydl.jpg)

What should I do instead?
I’m not suggesting that you avoid autoplaying videos, but I am suggesting that you always avoid the autoplay attribute. There is a better way.

1. Use `video.play()` in javascript world, which returns a promise. If the promise resolves, then autoplay worked, if the promise rejects then autoplay was blocked.
1. If the promise returned from `video.play()` rejects, then show a play button in the UI so that the user can click to play (the default video `controls` attribute will work just fine). If you are using your own custom controls and your javascript calls `video.play()` again as the result of an event that bubbled up from a user click, then it will work.
1. Consider starting with the video muted, this gives you a much lower chance of your `video.play()` call rejecting. You will want to show some kind of “muted” icon in the UI that the user can click to unmute (again, the default video `controls` attribute works great for that). You may notice that twitter and a lot of sites start videos in the muted state.
1. Have I mentioned showing controls for your player? Always make sure controls for your player are accessible. We have seen sites try to get fancy and be too minimalist by hiding controls. Inevitably, they run into situations where autoplay fails and the user has no way of clicking to make the video play. Make sure you do not fall into this trap.

## Here’s an example with vanilla javascript

```javascript
// get a reference to a <video> element
const videoEl = document.querySelector('video');

// attempt to call play() and catch if it fails
videoEl.play().then(() => {
  console.log('Autoplay success!');
}).catch((error) => {
  console.warning('Autoplay error', error);
});
```

## Here’s an example with React

If you look at mux.com you’ll see that we autoplay a video on the top of the home page.  I copied over how we did that and set up a demo here: https://o9s4w.csb.app/. The code is copied below and you can fork it and play around with the [Code Sandbox](https://codesandbox.io/s/autoplay-example-react-o9s4w).

Notice that we’re doing a few things here:

1. Try to call `video.play()` when the component loads.
1. Show the user a play/pause state in the UI by using the default `controls` attribute.
1. Start with the video in the `muted` state. Our video does not have audio, but if it did you would still want to start off in the muted state with the muted attribute, and show a mute/unmute icon in the UI.

```javascript
import React, { useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  const videoEl = useRef(null);

  const attemptPlay = () => {
    videoEl &&
      videoEl.current &&
      videoEl.current.play().catch(error => {
        console.error("Error attempting to play", error);
      });
  };

  useEffect(() => {
    attemptPlay();
  }, []);

  return (
    <div className="App">
      <h1>Autoplay example</h1>
      <div>
        <video
          style={{ maxWidth: "100%", width: "800px", margin: "0 auto" }}
          playsInline
          loop
          muted
          controls
          alt="All the devices"
          src="https://stream.mux.com/6fiGM5ChLz8T66ZZiuzk1KZuIKX8zJz00/medium.mp4"
          ref={videoEl}
        />
      </div>
    </div>
  );
}
```