files/en-us/web/api/htmlmediaelement/play/index.md
{{APIRef("HTML DOM")}}
The {{domxref("HTMLMediaElement")}}
play() method attempts to begin playback of the media.
It returns a {{jsxref("Promise")}} which is resolved when playback has been
successfully started.
Failure to begin playback for any reason, such as permission issues, result in the promise being rejected.
play()
None.
A {{jsxref("Promise")}} which is resolved when playback has been started, or is rejected if for any reason playback cannot be started.
[!NOTE] Browsers released before 2019 may not return a value from
play().
The promise's rejection handler is called with a {{domxref("DOMException")}} object passed in as its sole input parameter (as opposed to a traditional exception being thrown). Possible errors include:
NotAllowedError {{domxref("DOMException")}}
NotSupportedError {{domxref("DOMException")}}
Other exceptions may be reported, depending on browser implementation details, media player implementation, and so forth.
Although the term "autoplay" is usually thought of as referring to pages that
immediately begin playing media upon being loaded, web browsers' autoplay policies also
apply to any script-initiated playback of media, including calls to play().
If the {{Glossary("user agent")}} is configured not to allow automatic or
script-initiated playback of media, calling play() will cause the returned
promise to be immediately rejected with a NotAllowedError. Websites should
be prepared to handle this situation. For example, a site should not present a user
interface that assumes playback has begun automatically, but should instead update their
UI based on whether the returned promise is fulfilled or rejected. See the
example below for more information.
[!NOTE] The
play()method may cause the user to be asked to grant permission to play the media, resulting in a possible delay before the returned promise is resolved. Be sure your code doesn't expect an immediate response.
For even more in-depth information about autoplay and autoplay blocking, see our article Autoplay guide for media and Web Audio APIs.
This example demonstrates how to confirm that playback has begun and how to gracefully handle blocked automatic playback.
When this example is executed, it begins by collecting references to the {{HTMLElement("video")}} element as well as the {{HTMLElement("button")}} used to toggle playback on and off.
It then sets up an event handler for the {{domxref("Element/click_event", "click")}} event on the toggle button and attempts to automatically begin playback by calling the async playVideo() function.
A helper function toggleButton() lets us define what should happen in the code when we pass it a boolean value representing the playing state (e.g., toggleButton(true))
If playback is successful, the button text and its aria-label changes to "Pause".
If playback fails, the button and aria-label shows "Play".
This ensures that the playButton matches the playback state by watching for the resolution or rejection of the {{jsxref("Promise")}} returned by play():
<div class="video-box">
<video
id="video"
width="480"
loop
src="/shared-assets/videos/flower.mp4"></video>
<button type="button" id="play-button" aria-label="Play"></button>
</div>
let videoElem = document.getElementById("video");
let playButton = document.getElementById("play-button");
playButton.addEventListener("click", handlePlayButton);
playVideo();
function toggleButton(playing) {
if (playing) {
playButton.textContent = "Pause";
playButton.setAttribute("aria-label", "Pause");
} else {
playButton.textContent = "Play";
playButton.setAttribute("aria-label", "Play");
}
}
async function playVideo() {
try {
await videoElem.play();
toggleButton(true);
} catch (err) {
toggleButton(false);
}
}
function handlePlayButton() {
if (videoElem.paused) {
playVideo();
} else {
videoElem.pause();
toggleButton(false);
}
}
.video-box {
position: relative;
}
#video {
border: 2px solid black;
}
#play-button {
position: absolute;
top: 10px;
left: 10px;
padding: 8px 12px;
background-color: black;
color: white;
border: none;
cursor: pointer;
}
{{embedlivesample("handling-states", , "300")}}
{{Specifications}}
{{Compat}}