Screen Wake Lock API

· 4 min read · Updated April 24, 2026 · intermediate
javascript web-api wake-lock browser pwa

The Screen Wake Lock API prevents a device’s screen from dimming or turning off while your web app needs it to stay on. It’s useful for reading apps, video playback, navigation, and any scenario where hands are occupied.

Feature Detection

Before using the API, check for support:

if ('wakeLock' in navigator) {
  // supported
}

Support is in Chrome, Safari, and Firefox across desktop and mobile.

Requesting a Wake Lock

let wakeLock = null;

async function requestWakeLock() {
  try {
    wakeLock = await navigator.wakeLock.request('screen');
    console.log('Wake lock active');
  } catch (err) {
    console.error('Wake lock failed:', err);
  }
}

requestWakeLock();

navigator.wakeLock.request('screen') returns a Promise that resolves with a WakeLockSentinel object. The request can fail if the system is in low power mode, battery is critical, or the page is not visible.

The WakeLockSentinel Object

The sentinel is your handle to the lock. Store it and use it to release later:

const sentinel = await navigator.wakeLock.request('screen');

sentinel.release();  // manually release
sentinel.released;    // boolean — true if already released
sentinel.type;        // "screen" for screen wake lock

Once release() is called, the sentinel is done. The system can also release it automatically.

Automatic Release on Visibility Change

The wake lock is automatically released when the page becomes hidden. If the user switches tabs or minimizes the browser, the lock is gone. To re-acquire when the page becomes visible again:

let wakeLock = null;

async function requestWakeLock() {
  if (wakeLock !== null) return;

  try {
    wakeLock = await navigator.wakeLock.request('screen');
  } catch (err) {
    console.error('Wake lock request failed:', err);
  }
}

document.addEventListener('visibilitychange', async () => {
  if (document.visibilityState === 'visible') {
    await requestWakeLock();
  }
});

This matters for single-page apps where the user might navigate away and come back.

Checking Lock Status

You can’t query whether a wake lock is currently active directly. Track it yourself:

class WakeLockManager {
  #sentinel = null;

  get isActive() {
    return this.#sentinel !== null && !this.#sentinel.released;
  }

  async acquire() {
    if (this.isActive) return;
    try {
      this.#sentinel = await navigator.wakeLock.request('screen');
      this.#sentinel.addEventListener('release', () => {
        this.#sentinel = null;
      });
    } catch (err) {
      console.error('Failed to acquire wake lock:', err);
    }
  }

  async release() {
    if (this.#sentinel) {
      await this.#sentinel.release();
      this.#sentinel = null;
    }
  }
}

Using the 'release' event on the sentinel, you can keep the manager’s state in sync if the system releases the lock.

Handling the Release Event

The sentinel emits 'release' when the system releases the lock:

const sentinel = await navigator.wakeLock.request('screen');

sentinel.addEventListener('release', () => {
  console.log('Wake lock released by system');
  // e.g., user switched apps, battery low
});

This event is not cancelable. When it fires, the lock is already gone.

Complete Example: Video Player

class VideoWakeLock {
  #video = null;
  #sentinel = null;

  constructor(video) {
    this.#video = video;
  }

  async activate() {
    if (!('wakeLock' in navigator)) return;
    if (this.#sentinel) return;

    try {
      this.#sentinel = await navigator.wakeLock.request('screen');
    } catch (err) {
      console.warn('Wake lock not available:', err);
    }
  }

  async deactivate() {
    if (this.#sentinel) {
      await this.#sentinel.release();
      this.#sentinel = null;
    }
  }
}

const video = document.querySelector('video');
const wakeLock = new VideoWakeLock(video);

video.addEventListener('play', () => wakeLock.activate());
video.addEventListener('pause', () => wakeLock.deactivate());
video.addEventListener('ended', () => wakeLock.deactivate());

Permissions and Restrictions

The API requires the page to be visible. If your page is in a background tab, the request is rejected. The Permissions Policy header can also restrict access:

Permissions-Policy: screen-wake-lock=self

Without the permission, request() throws a NotAllowedError.

When to Use It

Good fits:

  • Recipe apps — keep screen on while hands are busy
  • Video players — don’t let the screen sleep mid-playback
  • Navigation — turn-by-turn directions without touching the phone
  • Presentations — keep the slides visible during a talk
  • Camera scanner — QR/barcode scanning where you hold the device

Don’t use it for things that don’t need the screen on. The API is a power user feature, not a general “my app is open” tool.

See Also