Idle Detection

IdleDetector reports whether the user has been inactive and whether the screen is locked -- using OS-level signals, not just tab focus. The threshold is minimum 60 seconds, and it requires explicit permission. Chromium only.

June 12, 20264 min read3 / 3

Chat apps show "Away" when you stop responding. Netflix asks "Still watching?" after you have not touched anything in a while. Both need the same thing: a reliable signal that the user is no longer present.

The Idle Detection API provides that signal from the operating system -- not just from the tab.

This distinction matters. A user who switches to WhatsApp to reply to a message is still active at the OS level, even though your web app's tab is in the background. The Idle Detection API sees that interaction and reports the user as active. A blur event on the window would not.

The Two States

The API reports two independent dimensions:

User state:

  • "active" -- the user has interacted with any app or the OS recently (mouse, keyboard, touch, anything)
  • "idle" -- no user interaction detected for at least the configured threshold

Screen state:

  • "unlocked" -- the screen is visible and accessible
  • "locked" -- the screen is off or the lock screen is showing

These states are independent. The screen can be locked while the user state is still "active" -- that happens when a user locks their phone immediately after using it.

Requesting Permission and Starting Detection

JavaScript
// Permission must be requested first const permission = await IdleDetector.requestPermission() if (permission !== 'granted') return // Create the detector and start it const detector = new IdleDetector() detector.addEventListener('change', () => { console.log('User state:', detector.userState) console.log('Screen state:', detector.screenState) }) await detector.start({ threshold: 60_000, // 60 seconds minimum -- browser enforces this floor signal: abortController.signal // optional: stop detection when aborted })

threshold sets how long the user must be inactive before userState flips to "idle". The browser enforces a minimum of 60 seconds -- you cannot detect inactivity at shorter intervals. This is intentional: shorter thresholds would make idle state useful for timing attacks.

Practical Uses

Chat presence. Set userState to "away" in your chat UI when the detector reports "idle". Reset to "active" when it returns to "active". This is how modern chat apps show whether a contact is currently at their device.

Reduce background work. When the user goes idle, lower the frequency of polling operations, pause non-critical animations, or defer expensive computations. The user is not watching -- save their battery.

"Are you still there?" Video or content streaming services use this to pause playback and prompt the user rather than waste bandwidth serving content no one is watching.

Lock-screen detection. When screenState becomes "locked", pause any audio or video the page might be playing -- the screen is off, the user has stepped away.

Idle Detection API: active/idle user state transitions, unlocked/locked screen state, and the setup flow ExpandIdle Detection API: active/idle user state transitions, unlocked/locked screen state, and the setup flow

The Privacy Tradeoff

The Idle Detection API requires explicit permission precisely because it reveals information about the user's behavior at the OS level. An idle state tells you the user stepped away, which can reveal information about their schedule or habits over time.

The 60-second minimum threshold and the permission requirement are the spec's mitigations. The API is Chromium-only -- Firefox and Safari have not implemented it, partly over these same privacy concerns.

Stopping Detection

Pass an AbortController signal to start() and call abort() to stop:

JavaScript
const controller = new AbortController() await detector.start({ threshold: 60_000, signal: controller.signal }) // Later, to stop: controller.abort()

The detector also stops automatically when the page is hidden or when the user revokes permission.

Support

Idle Detection is Chromium only. It works in Chrome and Edge. Firefox and Safari do not implement it.

JavaScript
if ('IdleDetector' in window) { // Idle Detection is available }

That closes out the device-state chapter. The next chapter shifts from reading device state to integrating with the operating system itself -- starting with what it means for a web app to be installed. PWA and OS Integration explains what installation unlocks and why it matters for every API that follows.

The Essentials

  1. userState is "active" or "idle" based on OS-level interaction -- not just your tab. Mouse movement in another app counts as active.
  2. screenState is "unlocked" or "locked" -- independent of user state.
  3. IdleDetector.requestPermission() is required first. Then detector.start({ threshold }).
  4. Minimum threshold is 60 seconds, browser-enforced. Cannot detect inactivity at shorter intervals.
  5. change event fires when either state changes. Stop with an AbortController signal.
  6. Chromium only. Safari and Firefox have not implemented it.

Further Reading and Watching