How to get hidden, autoplaying HTML5 audio on iOS (now with added hackiness!)

Let me start this article the same way I started my previous article about this topic: don’t autoplay audio. Autoplaying audio is the worst thing on the web and nobody will visit your site if you play audio without permission. It’s a bad, bad thing and people will hate you for it. Your dog will run away and your best friend will kick you in the face.

Now that that’s out of the way, here’s how you do it again. Apple removed support for my old hack (which wasn’t so much a hack as a correct usage of the spec) in iOS 4.2, as I thought they might.

Recently, I’ve needed support for hidden audio for a geolocation-based alarm (the article for it is going up very shortly also). Because iOS Safari now will only play audio after direct interaction from the user, I had to hack around a little bit.

Shut up and tell me how to do it already!

Okay, calm down. The basic premise of this hack is that you can load the audio before playing it – if the audio is loaded, a call to play will play it, interaction or no. The thing is, you still need interaction to load the audio. Now, I figured that every site is going to have some kind of interaction from the user. In my opinion, the likeliest is a scroll. Pretty much anything that your user is likely to do. For my needs, this is perfect – the user must click (tap) on a map to set the alarm. For most pages, the user will have to scroll. There are many evil, evil ways you could make your users incite hellish sounds upon themselves.

The code looks like this

<!DOCTYPE html>
function main(){

	//setTimeout("playAudio();",20000); //any call to playAudio will make the audio play after a click

document.onclick = function(){

function playAudio(){

<body onload="main();">
<div id="hidden_audio" style="display:none">
<audio id="audio" style="display:none" controls src="./alarm.mp3">

Now, as you can hopefully see, this is extremely simple. Add an old-style clickhandler to the body, load the audio in that, then call play whenever you feel like it. Don’t forget to hide your audio tag in a div with display:none. Easy, huh?

I was promised hackiness!

Too bad. This is a fairly by-the-book usage of the spec. The only hacking involved is making your user tap the page at all – for many users, this isn’t even a problem, they’ll just tap around by themselves.

This has been confirmed as working on iOS 4.3 on my iPhone, and iOS 4.3.1 on iPad. I’d be surprised if there was a way around this – perhaps Apple, or indeed the W3C, will implement a “This site would like to hurt your ears” warning, similar to the way it does for Geolocation.

About the Author

Carl Lange

I'm currently a Computer Games Development student at Carlow IT. I love programming and all things technical, and I'll learn anything if it's interesting. I'm passionate about technical education, and naturally about games. Check out my resume, and follow me on Twitter!

Visit Website


  1. andrewseid October 2, 2011

    looks like they broke it again in iOS 5 ;(

    method works for me in chrome or safari, just not on my iOS 5 iphone or ipad.



    • Author

      Damn. I’ll figure out a new way to do it once I’ve got iOS5. I know they’ve brought in stuff life position:fixed; to the browser, perhaps they’ve actually enabled the option? Unlikely enough, though. My next method involved making a large invisible div that acts as the controls for the player. Maybe that’ll work.

  2. it’s not working….

  3. hey carl!

    so iOS 5 has been out for a while now… did you figure out any new hacks?!


  4. Sadly, this is not possible. I had hoped you could keep a sound sprite in memory and use Sound Manager 2 to pay specific parts of the track, but alas this still requires .play()

  5. we want new hacks! come on carl!

Trackbacks for this post

  1. […] I had to invent a new way to get around iPhone Safari’s lack of autoloading sounds, which I detailed in this post) My biggest problem, and the app’s biggest flaw, is that on the iPhone, Safari […]