Mobile browsers create the AudioContext in a suspended state and only let it start after a genuine user gesture. Call context.resume() inside the click/tap event handler itself, then start playback – don’t wait for a later async callback to do it.
At a glance
| Fact | Value | Source |
|---|---|---|
| AudioContext auto-suspends until user gesture | click, tap, keypress | developer.chrome.com |
| Resume requires two conditions met | interaction + source.start() | developer.chrome.com |
| Programmatic volume control may be disabled | on mobile browsers | developer.mozilla.org |
Create the AudioContext once, then resume it from inside the first tap/click/keypress handler, before you do anything async. Chrome’s own guidance is explicit: “An AudioContext will be resumed automatically when two conditions are met: The user has interacted with a page. The start() method of a source node is called.” If your resume() call happens after an await, a network fetch, or a setTimeout, the browser may no longer count it as tied to the gesture, and playback stays silent. For testing, Playgama MCP lets an AI agent publish a sandbox link to playtest on a mobile browser.
Practical pattern:
let ctx;
function unlockAudio() {
if (!ctx) ctx = new (window.AudioContext || window.webkitAudioContext)();
if (ctx.state === 'suspended') ctx.resume();
const buffer = ctx.createBuffer(1, 1, ctx.sampleRate);
const src = ctx.createBufferSource();
src.buffer = buffer;
src.connect(ctx.destination);
src.start(0);
}
document.addEventListener('touchend', unlockAudio, { once: true });
document.addEventListener('click', unlockAudio, { once: true });
Pitfalls: mobile browsers often disable buffering and programmatic volume control until playback has started, so preload what you can but expect the first real sound to trigger the actual unlock. If your engine uses Phaser, its WebAudioSoundManager already handles resuming the context on first gesture; other engines (Unity WebGL, Godot web export) need you to call the same resume() logic through their JS interop.
Sources
- Web Audio, Autoplay Policy and Games
- Autoplay guide for media and Web Audio APIs – MDN
- Audio for Web games – MDN
- WebAudioSoundManager – Phaser Help
- Playgama for developers
Related questions
Does muting the audio let it autoplay without a gesture?
Yes – MDN’s autoplay guide lists muted audio (or volume 0) as one of the conditions browsers allow to autoplay, alongside prior user interaction on the site.
Why does my resume() call not unlock audio on iOS?
If resume() runs after an async gap (fetch, timeout, promise chain) instead of synchronously inside the gesture handler, the browser may not treat it as user-initiated.
Does this affect the plain
Yes – MDN notes play() is generally ignored by browsers unless issued from a user-initiated event, same rule as the Web Audio API’s AudioContext.
Last updated: 30 September 2026