Quick answer: Modern browsers block audio playback until the user has interacted with the page (click, tap, or key press). The Web Audio API context starts suspended and must be resumed by a user gesture. Do not play audio on "Start of layout" — instead, gate your first audio playback behind a touch, click, or key press event. Construct 3 will automatically resume the audio context on the first user interaction, but any Play actions issued before that interaction are silently dropped.
You add a "Play" audio action to the Start of Layout event, preview your project, and hear nothing. The game loads, the visuals are fine, but the background music is completely silent. You click a button or tap the screen, and suddenly the audio works for everything after that first interaction. This is not a Construct 3 bug — it is a browser security policy that affects every web game engine, and it has a straightforward fix once you understand why it exists.
The Symptom
Audio playback actions that run automatically — on "Start of layout", on a timer, or on any event that fires without direct user input — produce no sound. The browser console may show a warning like The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.
Once the player clicks, taps, or presses a key, all subsequent audio actions work perfectly. The problem is strictly limited to audio that tries to play before the very first user interaction on the page.
This affects all browsers to varying degrees. Chrome and Safari are the strictest enforcers. Firefox may allow autoplay in some contexts but has been tightening restrictions. The behavior is consistent in exported builds, not just in the Construct 3 preview.
A particularly confusing variant: you test on your development machine where the browser has learned that you frequently interact with localhost, so autoplay might be allowed. Then you deploy to a server and your players report no audio on launch. The autoplay policy can differ between origins and between browser profiles.
What Causes This
There are five contributing factors to understand:
1. Browser autoplay policy. Since 2018, all major browsers have enforced policies that prevent web pages from playing audio without user interaction. This was introduced to stop websites from auto-playing ads and videos. The policy applies to the Web Audio API (which Construct 3 uses internally), not just HTML5 <audio> elements. When a page loads, the AudioContext is created in a "suspended" state. It can only be resumed inside a user gesture event handler.
2. Web Audio API context suspension. Construct 3's Audio plugin uses the Web Audio API internally. When the engine initializes, it creates an AudioContext. The browser suspends this context immediately. Any play() calls made while the context is suspended are silently ignored — no error is thrown, the audio simply does not play. Construct 3 automatically calls audioContext.resume() when it detects the first user interaction, but it cannot do this preemptively.
3. Preloading does not bypass the policy. The "Preload" action downloads audio data into memory, but preloading and playback are separate operations. A preloaded audio file is ready to play instantly, but "ready to play" does not mean "allowed to play." The autoplay policy gates the actual audio output, not the loading of data.
4. Timing of the first interaction. The first user gesture must be a genuine interaction — a click, tap, or key press. Mouse movement alone does not count. Programmatic calls to click() do not count. The browser specifically requires that the event originates from physical user input. This means you cannot fake the interaction in code.
5. Mobile Safari additional restrictions. On iOS Safari, the restrictions are even tighter. Audio may need to be played (not just resumed) inside the user gesture callback itself. A common pattern that works on desktop — resuming the context on click, then playing audio on the next frame — can fail on iOS because the play call is no longer synchronously inside the gesture handler.
The Fix
Step 1: Add a "Click to Start" gate. The most reliable fix is to require a user interaction before your game begins. Create a title screen or splash layout with a "Tap to Play" prompt. Play your audio in response to that interaction.
// Layout: TitleScreen
// Event sheet:
+ Touch: On any touch start
-> Audio: Play "BackgroundMusic" looping
at volume 0 dB (tag "bgm")
-> System: Go to layout "Level1"
This guarantees that the audio context is resumed by the touch event before the Play action executes. The music will start playing and continue across the layout transition (the Audio object is always Global in Construct 3).
Step 2: Use a flag to defer audio until first interaction. If you cannot add a splash screen, use a boolean variable to track whether the user has interacted yet, and play queued audio when they do.
// Event sheet variables:
// HasInteracted (Boolean) = false
// MusicQueued (Boolean) = false
// On layout start, queue the music but do not play it:
+ System: On start of layout
-> System: Set MusicQueued to true
// Wait for user interaction:
+ Touch: On any touch start
+ System: HasInteracted = false
-> System: Set HasInteracted to true
-> Audio: Play "BackgroundMusic" looping
at volume 0 dB (tag "bgm")
// OR using keyboard:
+ Keyboard: On any key pressed
+ System: HasInteracted = false
-> System: Set HasInteracted to true
-> Audio: Play "BackgroundMusic" looping
at volume 0 dB (tag "bgm")
Step 3: Preload audio files for instant playback after interaction. While preloading does not bypass the autoplay policy, it ensures there is no loading delay once the user does interact. Set your audio files to preload in Project Settings, or use the Preload action explicitly.
// On the loader layout or start of the first layout:
+ System: On start of layout
-> Audio: Preload "BackgroundMusic"
-> Audio: Preload "ButtonClick"
-> Audio: Preload "PlayerJump"
// These files will be ready in memory when the user
// finally interacts and triggers playback.
Step 4: Use the silent audio trick for immediate context activation. A well-known workaround is to play a very short, silent audio file on the first user interaction. This forces the AudioContext to resume without the player hearing anything, and all subsequent audio playback works normally.
// Import a 0.1 second silent WAV file as "Silence"
+ Touch: On any touch start
+ System: HasInteracted = false
-> Audio: Play "Silence" not looping
at volume -100 dB (tag "init")
-> System: Set HasInteracted to true
// Now the AudioContext is active.
// All future Play actions will work immediately.
Step 5: Handle the scripting API directly (advanced). If you use Construct 3's scripting feature (JavaScript), you can interact with the AudioContext directly for finer control.
// In a script block or script file:
const runtime = getRuntime();
// Listen for the first user interaction
document.addEventListener("pointerdown", function initAudio() {
// Access the audio context via the runtime
const audioCtx = runtime.audio._audioContext;
if (audioCtx && audioCtx.state === "suspended") {
audioCtx.resume().then(() => {
console.log("AudioContext resumed successfully");
});
}
document.removeEventListener("pointerdown", initAudio);
}, { once: true });
Why This Works
The browser autoplay policy is a binary gate: before user interaction, audio is blocked; after interaction, it is allowed. There is no gradual escalation or permission prompt (unlike camera or microphone access). The very first click, tap, or key press flips the switch permanently for that page session.
Construct 3 hooks into this automatically. When the engine detects a user input event, it calls AudioContext.resume() internally. After that point, all audio actions work as expected. The problem is only with actions that run before this first interaction.
The "Click to Start" gate is the cleanest solution because it naturally ensures user interaction happens before any gameplay audio. Most commercial web games use this pattern. It doubles as a loading screen and gives the player agency over when the experience begins.
The silent audio trick works because the browser does not check the content of the audio — only that a play call happened inside a user gesture handler. Playing a silent clip is enough to activate the AudioContext, and from that point forward, all audio works regardless of whether it is triggered by user input or by game logic.
"Never fight the autoplay policy. Embrace the splash screen. Your players expect to tap before a game starts anyway — use that tap to unlock audio and load assets simultaneously."
Related Issues
If your audio works initially but stops after a layout change, the issue is likely that the Audio object lost its state — see object not found after layout change for persistence strategies. If your game saves audio settings but they reset on reload, check Local Storage data not persisting for the async pitfalls. For visual issues where animations do not play on game start, animation not changing on trigger covers similar timing problems. And if your game objects are not responding to touch input at all, collision not detected between objects may help diagnose touch target issues.
One tap unlocks all audio. Gate it behind a splash screen and move on.