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:
granted: The user has explicitly granted access. The application can access the hardware immediately via APIs such asnavigator.mediaDevices.getUserMedia().denied: The user has blocked access. Hardware requests will automatically reject without displaying a prompt.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:
- Camera:
{ name: 'camera' } - Microphone:
{ name: 'microphone' } - Geolocation:
{ name: 'geolocation' } - MIDI Devices:
{ name: 'midi', sysex: false }(orsysex: truefor System Exclusive support)
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
- Feature Detection: Always confirm that
navigator.permissionsandnavigator.permissions.queryare defined before calling them, as legacy environments do not support the API. - Error Handling: Wrap queries in
try...catchblocks. If a browser does not implement a specific permission descriptor name (e.g., throwing aTypeError), handle it gracefully by falling back to requesting access directly via the relevant hardware API.