โ‡ Back to Blog

A Missing iframe Attribute Mutes Every Game in Your Catalogue. Nobody Files a Bug.

Published on

Cross-origin iframes block Web Audio by default, so a licensed HTML5 game embedded on your portal stays silent until the wrapper delegates autoplay permission. That is one missing attribute on one tag, and it applies to every title you serve from a licensor's domain at once. On iOS there is a second, unrelated mute that the wrapper cannot fix at all โ€” it has to be handled inside the game bundle. Almost nobody reports either problem. They just stop playing.

Audio is the least-audited part of a licensed catalogue. Buyers check load time, they check mobile layout, some of them check the licence scope. Nobody sits with an iPhone on silent and a cross-origin embed and confirms that a match-3 makes a noise when a tile lands. Then the catalogue goes live, the session lengths come in below the licensor's own numbers, and the working theory becomes "our traffic is worse" rather than "our games are mute."

๐Ÿ”‡ Silence Is the Default, and It Is Deliberate

Browsers stopped trusting pages with sound years ago. Chrome's autoplay policy is explicit that developers can no longer assume audio will play when a user arrives, and should assume playback is blocked until the user interacts with the site. The policy covers <audio> and <video> elements, and since Chrome 70 it covers the Web Audio API too โ€” which is what every serious HTML5 game actually uses.

The mechanic matters more than the headline. An AudioContext created before the document has received a user gesture is created in the suspended state. It does not throw. It does not warn. It runs your whole audio graph into nothing until something calls resume() after a real click or tap. A game that builds its context on load and never checks the state will look, from the inside, like it is playing audio perfectly.

Chrome also grades sites. The Media Engagement Index tracks how often a given user actually plays media on a given origin and unblocks autoplay on the ones that score well; Chromium's documentation confirms the threshold is undisclosed and that Chrome ships with a global allowlist of over a thousand sites exempted from the policy on past metrics. You can inspect your own scores at chrome://media-engagement. On mobile the shortcut is different again โ€” a site added to the Home Screen gets the privilege outright.

There is one accommodation Chrome made specifically for games, and it is worth knowing because it papers over the problem on well-built titles: an AudioContext resumes automatically when the user has interacted with the page and the start() method of a source node is called. Games that fire a sound in response to input, rather than looping music from frame zero, tend to survive the policy without their developers ever learning it exists.

๐Ÿงฑ The Game Is on Somebody Else's Origin

Here is where a licensed catalogue diverges from a game you built. Your portal has whatever engagement history it has earned. The game does not run on your portal. It runs in an iframe pointed at the licensor's CDN, or at your own game subdomain, and Permissions Policy treats that as a different context.

The default allowlist for the autoplay feature is self. A cross-origin frame is not self. So the frame is denied, and MDN's Permissions Policy reference spells out the consequence: calls to play() without a user gesture reject the promise with a NotAllowedError DOMException, and the autoplay attribute is ignored entirely. Chromium's own autoplay page puts it plainly โ€” by default, embedded iframes can only play muted or silent content.

The fix at the wrapper is one attribute:

  • <iframe src="https://games.example.com/title" allow="autoplay">
  • Combine it with anything else the game needs: allow="autoplay; fullscreen"
  • If you are also applying sandbox, check it separately โ€” the two attributes are independent, and a sandbox that strips scripts or same-origin access will break audio unlock for reasons that have nothing to do with autoplay.

What you cannot do is patch it from outside. Chrome's guidance for game developers is direct on this point: the standard resume-on-interaction snippet will not help an AudioContext instantiated inside an iframe unless that snippet is included within the iframe itself. A portal operator with a licensed catalogue does not control the inside of the iframe. You can grant the permission; you cannot perform the unlock.

That single fact reframes the whole problem. Audio behaviour is not an operations task you schedule for next sprint. It is an intake requirement you enforce at the point of licensing, because after the deal closes your only lever is asking the licensor to rebuild a title.

๐Ÿ“ฑ iOS Has a Second Mute, and It Is Not the One You Fixed

Delegate autoplay, test on Android, ship. Then a player on an iPhone with the ringer switched off gets nothing โ€” while the video ad in your interstitial slot plays fine.

That inconsistency was filed against WebKit in March 2022 as bug 237322: Web Audio is muted when the iOS ringer is muted, but <audio> and <video> elements are not. The cause is which audio session each one lands in. Media elements route to the playback session. Web Audio historically landed in the ambient session, which the hardware ringer switch controls.

For years the field workaround was ugly and widely copied: play a short silent clip through an <audio> element on the first touch, which moves the page onto the media channel, then run the real Web Audio graph. Wikipedia shipped it. The thread records two complaints about it that anyone deploying it should read first โ€” it costs performance, and it hands the device lock-screen media controls for a page that is not playing media.

The actual fix arrived quietly. In September 2024 a WebKit engineer closed the bug as configuration changed with a one-liner: since iOS 17, set the audio session type to playback.

  • if ("audioSession" in navigator) { navigator.audioSession.type = "playback"; }
  • Session types include ambient, playback, transient, transient-solo and play-and-record. A game with background music wants playback; a game whose sound is incidental may legitimately want to stay ambient.
  • The same interface exposes a state of active, interrupted or inactive, plus a statechange event. That is how you recover audio after a phone call interrupts a session โ€” another failure your players will never report.

Two caveats, because this is newer than it sounds. MDN still marks AudioSession as experimental and explicitly not Baseline, on the grounds that it does not work in some of the most widely used browsers. The W3C Audio Session specification remains an editor's draft, and as of late 2025 Safari was the only engine that had implemented it. Feature-detect it, do not depend on it, and keep a graceful path for engines that ignore the property.

And note where that line of code has to live: inside the game. Same conclusion as the iframe unlock. This is a catalogue quality question, not a portal configuration question.

๐Ÿค– The Android Wrapper Repeats the Whole Problem

Portals that ship their web catalogue as an Android app hit the same wall behind a different API. Android's WebSettings exposes setMediaPlaybackRequiresUserGesture, available since API level 17, and WebView-wrapped portals routinely have to set it to false to get media playing without an explicit tap. If your APK is a WebView around the same remote game URLs, you now have three gates stacked: the WebView setting, the iframe delegation inside the page, and whatever the game does about its own audio context.

Do not blanket-disable the gesture requirement and consider it solved. Rewarded video needs a deliberate user action anyway, both as a product decision and because the ad SDKs expect one. Turning the gate off globally mostly buys you the ability to autoplay a music loop at someone who opened your app on a train, which is the behaviour the policy was written to stop. If you are running a catalogue across both web and Android builds, the audio path deserves its own test matrix rather than a copied setting.

๐Ÿงช Seven Checks Before a Title Enters the Catalogue

Run these on every candidate title, on a real phone, before the licence is signed rather than after. They take about four minutes per game and they are the only leverage you have.

  1. Cross-origin embed, autoplay delegated. Load the game in an iframe on a different origin with allow="autoplay". Sound on first input? Pass.
  2. Cross-origin embed, autoplay withheld. Same test without the attribute. A well-built game should still produce sound once the player taps inside the frame, because the gesture happens in the frame. If it is dead either way, the game is unlocking against the wrong document.
  3. iPhone with the ringer off. The single most revealing test in the list, and the one nobody runs.
  4. Interruption recovery. Take a call, or trigger any system audio interruption, and return to the game. Does sound come back, or does the rest of the session run silent?
  5. Mute toggle, and whether it persists. A player who mutes on the third game should not be re-muting on the fourth.
  6. Cold load with no interaction. Nothing should play. If music starts before a gesture on any engine, the title is written against an assumption that has been false since 2018 and other things in it will be stale too.
  7. Ask what the game does on load. Whether it constructs the AudioContext eagerly and calls resume(), or lazily on first input, tells you more about the developer's maintenance habits than any spec sheet.

๐Ÿšซ Five Ways Portals Get This Wrong

  • Testing exclusively in desktop Chrome on the office machine. That browser has a Media Engagement score for your domain built up by the team, which is the one environment where the policy is most likely to be relaxed. It is the worst possible test bed and the most common one.
  • Adding allow="autoplay" and declaring the issue closed. It fixes the delegation. It does nothing for the iOS ringer path, nothing for interruption recovery, and nothing for a game that never calls resume().
  • Trying to unlock from the parent frame. Chrome documents that this does not work across the frame boundary. Portals still ship it, see it pass on same-origin staging, and watch it fail in production where the games are on the licensor's CDN.
  • Auto-playing a music bed the moment a game tile is clicked. Even where the browser permits it, it trains users to mute your tab, and muting is one of the behaviours that feeds Chrome's engagement scoring in the wrong direction.
  • Filing it as "a few games have sound bugs." It is not per-title until you have ruled out the wrapper. One attribute on one embed template can mute a thousand games, and a per-title bug queue will never find that.

๐Ÿ“Š Measure It, Because Nobody Will Tell You

Players do not report silence. They assume the game is like that, or they assume they broke something, and they leave. If you want a number, you have to generate it yourself:

  • Have the game report its AudioContext state a few seconds after start. Still suspended is a failure event. Segment it by browser, OS version and whether the frame was cross-origin.
  • Compare session length between sessions that produced audio and sessions that did not, on the same titles. That is your internal cost figure, and it will be more useful than any benchmark.
  • Watch the same split on rewarded video completion. If the ad renders inside the same frame as the game, the permission story applies to the ad's audio as well as the game's.

I have not found a credible public figure for how much a silent soundtrack costs a casual web game's session length, and I am not going to invent one. Treat it as unmeasured rather than as zero โ€” and then measure it on your own traffic, where the answer actually applies.

๐ŸŽฎ Where a Licensed Catalogue Fits

This is one of the practical reasons catalogue provenance matters. Forestry Games has licensed games since 2017 and maintains a catalogue of 1,049 titles across HTML5 and Android, developed in-house and with partners, and questions like "does this title unlock its own audio context inside a cross-origin frame" are exactly the kind of thing a licensor should be able to answer about its own builds rather than leaving to a buyer's QA. If you are assembling a portal, ask the question during evaluation โ€” of us or of anyone else. A licensor who has never thought about it is telling you something about the rest of the catalogue. You can work through the full catalogue or the portal setup with the audio checks above in hand.

๐Ÿงญ What to Fix This Week

Open your portal on an iPhone with the ringer switch off and play three games. Then open the same three in desktop Firefox, which has no engagement-based exemption to bail you out. If any of them are silent, start at the wrapper: check that your embed template carries allow="autoplay", and check it in the template rather than on one page, because the interesting failure is the one that is identical across every game you serve.

If the wrapper is correct and titles are still mute, the problem is inside the bundles, and that becomes a licensor conversation โ€” a list of specific titles, a specific failure mode, and a request. Add the seven checks to your intake process so the next hundred titles arrive already tested. It is four minutes a game against a defect class that is invisible in every dashboard you currently look at.

Related Reading

Google TV Hit 300 Million Devices. A Touch-First Game Catalogue Reaches None of Them.

American Puts Screens Back in Every Narrowbody Seat. An Ad-Funded Game Still Earns Nothing Up There.

WebGPU Landed in Every Browser. A Casual Catalogue Is Right to Ignore It.

Every Licensee Ships the Same Catalogue. Google Play Calls That โ€œRepetitive Content.โ€

MFA Spend Fell to 0.39%. If Your Game Portal Got Classified, Nobody Sends You a Letter.

Every Network Caps a Playable at 5 MB. That's Why It Can't Double as Your Campaign Game.

Browse all posts โ†’