How the Web Audio API is used for browser fingerprinting

When generating a browser identifier, we can read browser attributes directly or use attribute processing techniques first. One of the creative techniques that we’ll discuss today is audio fingerprinting.

Using an Oscillator and a Compressor they can basically calculate a specific number that identifies you.

Every browser we have on our testing laptops generate a different value. This value is very stable and remains the same in incognito mode.

And this only takes a few ms to calculate! 🤯

How the Web Audio API is used for browser fingerprinting →

Listen to your Web Pages

Always notice how in sci-fi movies the computers make those weird bleepy sounds?

Tom Hicks has created a JavaScript snippet that combines MutationObserver with AudioContext to recreate that effect.

Copy this into the console of any web page that is interactive and doesn’t do hard reloads. You will hear your DOM changes as different pitches of audio.


const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(function(mutationsList) {
  const oscillator = audioCtx.createOscillator()

  oscillator.connect(audioCtx.destination)
  oscillator.type = "sine"
  oscillator.frequency.setValueAtTime(
    Math.log(mutationsList.length + 5) * 880,
    audioCtx.currentTime,
  )

  oscillator.start()
  oscillator.stop(audioCtx.currentTime + 0.01)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})

Try it on Facebook for example. It beeps all over the place 😆

There’s also an alternate version that mimics the effect as heard on TV better:


const audioCtx = new window.AudioContext();
const oscillator = audioCtx.createOscillator();
oscillator.connect(audioCtx.destination);
oscillator.type = "sine";

let numItems = 0

oscillator.frequency.setValueAtTime(
  1,
  audioCtx.currentTime
);

oscillator.start();

const observer = new MutationObserver(function (mutationsList) {
  numItems += mutationsList.length

  oscillator.frequency.setValueAtTime(
    Math.log(numItems + 1) * 440,
    audioCtx.currentTime
  );

  setTimeout(() => {
    numItems -= mutationsList.length
    if (numItems === 0) {
      oscillator.frequency.setValueAtTime(
          1,
          audioCtx.currentTime
        )
    } else {
        oscillator.frequency.setValueAtTime(
          Math.log(numItems + 1) * 440,
          audioCtx.currentTime
        )
    }
  }, 100)
});

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true
});

There’s also a browser extension available, but be warned: there’s no off switch (you’ll have to remove it to disable it)

Feeding the Audio Graph – Using Web Audio’s AnalyserNode

Good article on 24ways (yes, that still is a thing) on using Web Audio’s AnalyserNode.

const waveform = new Uint8Array(analyser.fftSize);
const frequencies = new Uint8Array(analyser.frequencyBinCount);
const ctx = canvas.getContext('2d');

const loop = () => {
    requestAnimationFrame(loop);
    analyser.getByteTimeDomainData(waveform);
    analyser.getByteFrequencyData(frequencies);

    ctx.beginPath();
    waveform.forEach((f, i) => ctx.lineTo(i, f));
    ctx.lineTo(0,255);
    frequencies.forEach((f, i) => ctx.lineTo(i, 255-f));
    ctx.stroke();
}

loop();

I especially like the demo where the emoji are animated based on the frequency.

Feeding the Audio Graph →

audio-effects – Create Audio Effects Using the Web Audio API

Great stuff by Sam Bellen, in which me mimics the effect-pedals for guitars:

Audio-effects is a JavaScript library to create audio effects using the Web Audio API. This library contains the Volume, Distortion, Delay, Flanger, Reverb, and Tremolo effects

He recently gave a talk about this at JSConf Budapest 2016 and at a local Fronteers Meetup:

audio-effects (GitHub) →

Sidenote: To play audio in browsers I’m still a huge fan of Howler.

Lightyear.fm – A journey through space, time, and music

lightyearfm

Radio broadcasts leave Earth at the speed of light and travel outwards into space. Follow them through the Milky Way as you scroll backwards through time and listen to what the stars hear.

Built using Three.js. Taking a look at the source code reveals all tracks used.

And oh, don’t forget the “Inverse Square Law of Propagation”:

Although Lightyear.fm has radiowaves reaching over 100 lightyears into space, due to the Inverse Square Law of Propagation, any terrestrial radio broadcast would become nothing but background noise just a few light years away from Earth.

Lightyear.fm →