HTMLAudio (<audio>)

Audio (<audio>)

Before HTML5, playing audio in a browser meant relying on a plugin like Flash or QuickTime. The <audio> element made sound a native part of the web platform — a built-in player, a JavaScript API to control it, and no plugins required.

Basic Usage

audio-basic.html

HTML
<audio src="podcast-episode-1.mp3" controls></audio>

That single line renders a native player with play/pause, a seek bar, volume control, and (in most browsers) a download/options menu — all without a byte of JavaScript.

Key Attributes

Attribute

Effect

controls

Shows the browser’s native play/pause/volume UI. Omit it if you plan to build your own controls with JavaScript.

autoplay

Starts playback automatically on load — heavily restricted by browsers (see below).

loop

Restarts playback automatically when it reaches the end.

muted

Starts (and stays, until changed) with the volume muted.

preload

Hints how much to load ahead of time: none, metadata, or auto.

audio-attributes.html

HTML
<audio src="ambient-loop.mp3" controls loop preload="auto"></audio>

<!-- Muted autoplay background audio (still likely blocked — see warning) -->
<audio src="background.mp3" autoplay muted loop></audio>
preload in Detail

Value

Meaning

none

Don't preload anything — good when you're not sure the user will play it (e.g. many players on one page).

metadata

Load only duration/dimensions, not the audio data itself. A common default compromise.

auto

Let the browser decide — often means "load as much as reasonably possible" ahead of playback.

preload is only a hint
Browsers are free to ignore preload entirely — for example, on a metered mobile connection many browsers won't preload regardless of the value you set.
Multiple <source> for Format Fallback

Not every browser supports every audio codec. Instead of a single src on the <audio> tag, you can provide multiple <source> children — the browser picks the first one whose type it can play.

audio-sources.html

HTML
<audio controls>
  <source src="episode-1.opus" type="audio/ogg; codecs=opus" />
  <source src="episode-1.aac" type="audio/aac" />
  <source src="episode-1.mp3" type="audio/mpeg" />

  Your browser doesn't support HTML5 audio.
  <a href="episode-1.mp3">Download the audio file</a> instead.
</audio>
  • Sources are tried in order — put your preferred/smallest format first.

  • Text (and any markup) inside <audio> after the <source> elements is fallback content shown only if the browser supports neither <audio> nor any listed source.

  • MP3 and AAC have near-universal support today, making a single <audio src="..."> often good enough — multiple sources matter most for smaller/free codecs like Opus/Vorbis.

Autoplay Restrictions

Every major browser restricts autoplay with sound to prevent an unpleasant, spammy web. The specifics differ, but the general rule is consistent:

  • Autoplay with sound is usually blocked unless the user has previously interacted with the site, or the site has built up a "media engagement" history.

  • Autoplay is reliably allowed only when the element is also muted.

  • Calling .play() from JavaScript returns a Promise that rejects if autoplay was blocked — always handle that rejection instead of assuming playback started.

autoplay-handling.html

HTML
<audio id="player" src="track.mp3"></audio>

<script>
  const player = document.getElementById('player');

  player.play().catch((error) => {
    console.log('Autoplay was blocked:', error);
    // Show a "tap to play" button instead
  });
</script>
Never assume autoplay works
Always design for the case where autoplay is silently blocked — typically by showing a visible play button the user can tap, since a click/tap always counts as user interaction and unblocks playback.
Basic JavaScript Control

audio-js-control.html

HTML
<audio id="player" src="track.mp3"></audio>
<button id="play-pause">Play</button>

<script>
  const player = document.getElementById('player');
  const btn = document.getElementById('play-pause');

  btn.addEventListener('click', () => {
    if (player.paused) {
      player.play();
      btn.textContent = 'Pause';
    } else {
      player.pause();
      btn.textContent = 'Play';
    }
  });
</script>
Accessibility
If audio conveys spoken content (a podcast, an interview), provide a text transcript nearby — it benefits deaf and hard-of-hearing users, and it's also indexable by search engines, unlike the audio itself.
Quick recap
Use controls for a native player, provide multiple <source> elements for codec fallback, never rely on unmuted autoplay, and always handle the rejected Promise from .play().