How to Query Hardware Permissions in JavaScript

The Permissions API provides a standardized programmatic interface for querying the authorization status of hardware and sensitive browser capabilities—such as webcams, microphones, and geolocation—without triggering immediate permission prompts. This article details how to use navigator.permissions.query() to inspect device access states, listen for runtime permission changes, and handle hardware descriptors accurately in modern JavaScript.

The navigator.permissions.query() Method

The core of the Permissions API is the navigator.permissions.query() method. It accepts a PermissionDescriptor object and returns a Promise that resolves to a PermissionStatus object.

async function checkCameraPermission() {
  try {
    const status = await navigator.permissions.query({ name: 'camera' });
    console.log(`Camera status: ${status.state}`);
  } catch (error) {
    console.error('Permission query failed:', error);
  }
}

Permission States

The PermissionStatus.state property returns one of three string values:

  1. granted: The user has explicitly granted access. The application can access the hardware immediately via APIs such as navigator.mediaDevices.getUserMedia().
  2. denied: The user has blocked access. Hardware requests will automatically reject without displaying a prompt.
  3. prompt: The user has not yet decided. Attempting to access the hardware will trigger a browser permission dialog.

Querying Different Hardware Capabilities

Hardware access queries require passing the specific feature name in the descriptor object. Common hardware feature names include:

async function checkHardwareAccess() {
  const hardwareFeatures = ['camera', 'microphone', 'geolocation'];

  for (const name of hardwareFeatures) {
    try {
      const permission = await navigator.permissions.query({ name });
      console.log(`${name}: ${permission.state}`);
    } catch (err) {
      console.warn(`${name} permission query is not supported by this browser.`);
    }
  }
}

Monitoring Real-Time Permission Changes

Users can revoke or grant permissions at any time via browser settings. The PermissionStatus object inherits from EventTarget and exposes an onchange event handler to track these updates live.

async function monitorMicrophone() {
  const status = await navigator.permissions.query({ name: 'microphone' });

  status.onchange = () => {
    console.log(`Microphone permission changed to: ${status.state}`);
    if (status.state === 'granted') {
      // Enable UI controls for audio input
    } else {
      // Disable UI controls
    }
  };
}

Best Practices and Fallback Handling