Browser Autoplay Audio Policy

In my old blog, I talked about one of the things that bothers me about digital wedding invitations which is background music that starts playing the moment I click “Open Invitation.”
I thought it was a design choice, audio wired to a click rather than to page load. Turns out it’s a browser constraint.
Browsers block autoplay by default
The browser autoplay policy is a rule that prevents audio and video from playing automatically on page load without prior user interaction. Most major browsers enforce this. Audio won’t play unless the user has already clicked or typed on the page. You can’t fake it in code. Even if you dispatch a synthetic click event or call .play() programmatically, the browser knows the difference and will block it.
This was introduced to stop pages from blasting audio at people who never asked for it. If you’ve ever opened a tab and immediately heard something you didn’t expect, you already understand why this policy exists.
So when a wedding invitation plays music only after you click “Open Invitation,” the developer didn’t make some deliberate UX decision to put the trigger there. That’s just where it’ll work.
Where I ran into this
I hit this issue while trying to add two audio easter eggs to my wedding invitation.
The first was simple: clicking the logo at the bottom of the invitation page plays a sound. That works fine since it’s directly triggered by a click.
The second was trickier. The URL structure for the invitation uses a unique 6-character code per guest where a non-existent code leads to a 404. I thought it’d be funny to have audio play on that 404, a little gotcha for anyone trying to guess their way in.
I assumed it would just work, but it didn’t.
The 404 is a separate page load and the code is straightforward:
<audio id="notfound-audio" src="/audio/hey-foreign-stooges.mp3" preload="auto" />
<script> const nfAudio = document.getElementById('notfound-audio') if (nfAudio) { nfAudio.play().catch(() => {}) }</script>It just calls .play() immediately on load, and with no prior interaction, the browser blocks it.
The workaround
The invitation already had an index page where guests enter their code before reaching the invite, and that ended up being the workaround. Without something like that in the middle, every path to the 404 is a direct navigation with no prior user gesture, so the audio gets blocked every time.
That index page changes things. Someone opens it, types a random code, submits the form. The lookup fails, they land on the 404, but because the redirect came from a real form submission, some browsers carry the gesture context forward. The 404 is allowed to autoplay.
If someone navigates directly to a bad URL, none of that applies. The page loads, play() runs, the browser blocks it, the catch swallows the error silently. No audio.
The video below shows the path that works: opening the index page, submitting a non-existent code, and landing on the 404 with the audio playing. This is from a template I made based on the same project, not my actual wedding invitation.
The rule
Audio won’t autoplay without prior user interaction on that page. That interaction has to be real, a click or key press, not a synthetic event dispatched from JavaScript. And if the navigation to that page was triggered by a user gesture on the previous page, the restriction doesn’t apply.
That last part is what most people don’t know about, and it’s what makes the 404 trick work. It’s intentional behavior designed to account for user-initiated navigation.

