👀 Live Preview
Load the audio — when enough data is buffered, status updates:
Waiting for canplay…

The oncanplay attribute is an inline event handler that runs JavaScript when the canplay event fires. That happens on <audio> and <video> when the browser has buffered enough data that playback can start. Use it to hide loading spinners, enable custom play buttons, or log readiness. It does not mean the entire file is downloaded—only that playback can begin. For uninterrupted playback through the end, see oncanplaythrough.
Inline JS.
Media event.
Media elements.
Start vs full buffer.
Preferred way.
Property API.
oncanplay AttributeThe primary purpose of oncanplay is to react when media becomes ready to start. You might hide a “Loading…” overlay, enable a custom play button, start autoplay (where allowed), or sync UI with buffer state. The event is part of the media loading lifecycle alongside loadedmetadata, loadeddata, and canplaythrough.
The old reference used alert() in demos—avoid that in real apps. Status text or UI updates are clearer. Also note: canplay can fire multiple times if the user seeks or network conditions cause re-buffering.
Production code should use video.addEventListener("canplay", handler). Inline oncanplay on <audio> or <video> works for learning but separates concerns less cleanly.
Set oncanplay on audio or video, or assign element.oncanplay:
<script>
function handleCanPlay() {
console.log("Media can start playing.");
}
</script>
<audio controls oncanplay="handleCanPlay()">
<source src="song.mp3" type="audio/mpeg">
</audio>canplay event fires.<audio> and <video> media elements.media.oncanplay = function() { … }.media.addEventListener("canplay", handler).The oncanplay attribute accepts a string of JavaScript code:
oncanplay="handleCanPlay()" — Call a named function.oncanplay="hideLoader()" — Inline statement.video.oncanplay = () => { … } assigns the handler.const video = document.getElementById("clip");
video.addEventListener("canplay", () => {
document.getElementById("loader").hidden = true;
});
video.addEventListener("waiting", () => {
document.getElementById("loader").hidden = false;
});| Event | When it fires | Handler |
|---|---|---|
canplay | Enough data to start | oncanplay |
canplaythrough | Can play to end (estimate) | oncanplaythrough |
loadeddata | First frame ready | onloadeddata |
| Hide loader | In canplay handler | Common pattern |
| Re-buffer | waiting then canplay again | May repeat |
| Target | Supported? | Notes |
|---|---|---|
<audio> | Yes | Inline oncanplay on audio |
<video> | Yes | Most common use |
<source> | No | Event fires on parent media element |
<input>, <img> | No | Not media canplay events |
oncanplay vs oncanplaythrough vs onloadeddata| Handler | When it fires | Typical use |
|---|---|---|
onloadeddata | First frame of media available | Show poster / first frame |
oncanplay | Enough buffered to start | Enable play button, hide loader |
oncanplaythrough | Enough buffered to play through | Autoplay long content confidently |
Inline oncanplay on audio, addEventListener on video, and media load event order.
Load the audio — when enough data is buffered, status updates:
Waiting for canplay…
Run a function when playback can start:
<audio controls oncanplay="handleCanPlay()">
<source src="song.mp3" type="audio/mpeg">
</audio>
<script>
function handleCanPlay() {
console.log("Media can start playing.");
}
</script>The browser fires canplay on the audio element when playback can begin. The inline oncanplay attribute wires up the handler.
Attach the handler with addEventListener:
<script>
document.getElementById("clip").addEventListener("canplay", function () {
console.log("Video ready to play.");
});
// Or property form:
document.getElementById("clip").oncanplay = function () { /* … */ };
</script>Register the listener once at page load. When the video buffers enough data, canplay runs your readiness code.
See where canplay fits in the load sequence:
audio.addEventListener("loadedmetadata", () => { /* duration known */ });
audio.addEventListener("loadeddata", () => { /* first frame */ });
audio.addEventListener("canplay", () => { /* can start */ });
audio.addEventListener("canplaythrough", () => { /* can play through */ });canplay means “ready to start,” not “fully downloaded.” Use canplaythrough when you need confidence for uninterrupted playback.
canplay to enable controls, not surprise playback.controls attribute supports keyboard users; custom players need full keyboard support.Browser fetches the file.
Metadata and frames arrive.
Enough to start playback.
Enable play UI.
The canplay event and oncanplay handler are supported in all modern browsers on <audio> and <video> elements — Chrome, Firefox, Safari, and Edge.
oncanplay supportAll major browsers fire the underlying event and honor the oncanplay handler attribute.
Bottom line: Universal support on media elements. Test with slow network throttling to see canplay timing.
oncanplay.waiting, hide again on canplay.audio/video for unsupported browsers.preload="metadata" affects when events fire.The oncanplay attribute runs JavaScript when enough media data is buffered and the canplay event fires on audio or video. Use it to enable playback UI and hide loading indicators.
Prefer addEventListener("canplay", …), pair with waiting for re-buffering, and use oncanplaythrough when you need confidence for uninterrupted playback.
oncanplayBookmark these before wiring your next event handler.
canplay fires.
EventMedia only.
ScopeOn canplay.
PatternPreferred.
ModernCan re-fire.
Notecanplay event fires — when enough media data is buffered that playback can start.audio and video elements. The event fires on the media element loading the resource.oncanplay means playback can start. oncanplaythrough means the browser estimates it can play through without stopping to buffer.media.addEventListener("canplay", …). Inline oncanplay works for simple demos.waiting), canplay can fire again when enough data is available.Practice inline oncanplay, addEventListener, and media event order in the Try It editor.
5 people found this page helpful