Unlock JavaScript Web Audio in Safari and Chrome

Update: This is now necessary for Chrome, too. You might see this message in the console:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

I've had much frustration dealing with Web Audio in Safari. Especially with ScriptProcessorNode, it just doesn't want to work. Here's a solution I've arrived at. This is written in ES6 JavaScript, and will work in Safari (iOS and macOS) and Chrome:

function unlockAudioContext(audioCtx) {
  if (context.state !== 'suspended') return;
  const b = document.body;
  const events = ['touchstart','touchend', 'mousedown','keydown'];
  events.forEach(e => b.addEventListener(e, unlock, false));
  function unlock() { audioCtx.resume().then(clean); }
  function clean() { events.forEach(e => b.removeEventListener(e, unlock)); }

Call the function immediately after creating the audio context, like this:

const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

Here's something very similar in ES5:

function unlockAudioContext(audioCtx) {
  if (audioCtx.state === 'suspended') {
    var events = ['touchstart', 'touchend', 'mousedown', 'keydown'];
    var unlock = function unlock() {
      events.forEach(function (event) {
        document.body.removeEventListener(event, unlock)

    events.forEach(function (event) {
      document.body.addEventListener(event, unlock, false)

2 ResponsesLeave a Reply

  1. Digbalay Bose

     /  May 15, 2019 Quote

    Thanks for the code Matt ! The code worked for safari from macbooks but when I tried it from safari in iphone and ipad, i could not hear any sound.

  2. James Moore

     /  July 6, 2019 Quote

    Thanks. Finally something that worked for me. The only problem I have now is that I have to click the button twice or second click outside the button to hear the audio. After 4 times or so, it just stops working and I have to refresh the browser to get it to work again. Very frustrating!

Leave a Reply to James Moore