Ios Sensor Permission

iOS 13 silently added a sensor permission dialog that broke thousands of web experiences. Here is how DeviceMotionEvent.requestPermission works and the privacy reason it exists.

June 10, 20265 min read3 / 17

In 2019, immersive web experiences and games built on iOS device motion stopped working. Not crashing -- the code ran fine. The motion events just silently produced nothing.

There was no release note. No deprecation warning. No API change log.

Apple had added a permission dialog for sensor access and told nobody.

Why Apple Made the Change

The reason was fingerprinting.

Advertising scripts embedded in iframes were reading the accelerometer and gyroscope to build a fingerprint of the device. The motion data -- subtle variations in how a specific device vibrates and moves -- is surprisingly unique. No user interaction required. No visible dialog. Just a script quietly reading hardware data and building a profile.

Apple's fix was to require explicit user permission for DeviceMotionEvent and DeviceOrientationEvent. Any site that wanted to read these sensors would now have to show a dialog. Ad scripts embedded in iframes wouldn't bother -- the UX cost killed the incentive.

The catch: Apple implemented this in iOS 13 without documenting the new API anywhere. A developer eventually found the DeviceMotionEvent.requestPermission() method by reading the WebKit source code. Someone from the WebKit team confirmed it on Twitter. There was no official documentation for months.

A feature that silently gated an existing API, discovered in source code, confirmed on Twitter. That's how iOS sensor permissions entered the ecosystem.

The Permission Pattern

The permission only applies to iOS. On Android and desktop, you still just add the event listener directly. This means you need to detect which path you're on before doing anything.

The detection is simple: check whether DeviceMotionEvent.requestPermission is a function. If it is, you're on iOS 13+. If it isn't, you're on Android or a desktop browser.

The call must come from a user gesture. A button click, not a page-load handler. Apple enforces this -- calling requestPermission() outside of a gesture handler silently fails.

JavaScript
async function enableMotionSensors() { if (typeof DeviceMotionEvent.requestPermission === 'function') { // iOS 13+ -- must request permission const permission = await DeviceMotionEvent.requestPermission(); if (permission === 'granted') { window.addEventListener('devicemotion', handleMotion); } else { showFallbackUI(); } } else { // Android, Firefox, desktop -- no permission needed window.addEventListener('devicemotion', handleMotion); } } // Must be called from a button click or similar user gesture document.getElementById('enable-sensors').addEventListener('click', enableMotionSensors);

The return value is the string 'granted' or 'denied' -- not a Permission object like the Permissions API returns. It's its own separate mechanism.

iOS sensor permission flow vs Android direct access ExpandiOS sensor permission flow vs Android direct access

What Broke and Why

The sites that broke were almost universally games, 360-degree photo viewers, and interactive experiences. Before iOS 13, developers added window.addEventListener('devicemotion', ...) directly in their initialization code -- sometimes on page load, sometimes triggered by a button but without the permission call.

After iOS 13, those listeners registered successfully but received no events. The page appeared to work. No errors. The sensor data just never arrived.

Debugging this was particularly frustrating because the behavior was correct on Android, correct on desktop, and silent on iOS. No console warning. No error event. The listener was there. The data wasn't.

The fix is one conditional block. But you have to know it exists to add it.

The Ambient Light Parallel

The iOS sensor permission wasn't the only time a privacy concern quietly changed how sensors work.

Chrome removed the Ambient Light Sensor from stable builds for a similar reason. Someone realized that the screen's own brightness affects the light reading from the ambient sensor. An attacker could load a page with known bright and dark content, watch how the ambient light reading changed, and infer what was showing on neighboring browser tabs.

The attack surface was narrow but real. Chrome and Firefox both removed the ambient light sensor from stable builds. It's still accessible behind the #enable-generic-sensor-extra-classes flag in Chrome flags, but it's been experimental for years now.

Both cases -- iOS 13 motion permissions and ambient light removal -- illustrate the same pattern: sensor data that seems harmless can become a side channel for extracting information users didn't intend to share. The browser vendors' response has generally been to restrict access rather than allow and monitor.

What This Means in Practice

If you're building a sensor-based experience, the iOS permission check is one required addition that most tutorials skip:

  • Always call requestPermission() from a user gesture, not page load
  • Handle both the 'granted' and 'denied' outcomes explicitly
  • Test on an actual iPhone -- the Android behavior won't reveal the issue
  • Don't expect the Permissions API to cover this -- it's a separate iOS mechanism

For the ambient light sensor: treat it as unavailable in production. Design the experience to work without it. If it happens to be available (a user who enabled the flag), read it as an enhancement -- not a requirement.

The Essentials

  1. iOS 13 added DeviceMotionEvent.requestPermission() without documentation. It breaks silently if called outside a user gesture.
  2. The return value is 'granted' or 'denied' -- a string, not a Permission object. Handle both.
  3. Detection is typeof DeviceMotionEvent.requestPermission === 'function'. True on iOS 13+, false everywhere else.
  4. The ambient light sensor was removed from stable Chrome and Firefox after researchers showed it could leak information about neighboring tabs.
  5. Both restrictions follow the same pattern: sensor data that looks harmless can become a privacy side channel.

Further Reading and Watching