Permissions-Policy
Unrestricted access to browser features like camera, microphone, and geolocation creates privacy and security risks. The Permissions-Policy response header controls which features a page and its embedded iframes are allowed to use.
Usage
The Permissions-Policy response header restricts which browser features are allowed in the current frame. Each policy pairs a feature directive with an allowlist defining which Origins access the feature.
Permissions-Policy: <directive>=<allowlist>
Directives
The directive name identifies the browser feature to control. A non-exhaustive list of standardized directives:
accelerometer: device motion sensorautoplay: media autoplaycamera: video captureencrypted-media: Encrypted Media Extensionsfullscreen: fullscreen modegeolocation: location accessgyroscope: orientation sensormagnetometer: magnetic field sensormicrophone: audio capturemidi: Web MIDI APIpayment: Payment Request APIpicture-in-picture: PiP modesync-xhr: synchronous XMLHttpRequestunload: unload event handlersusb: WebUSB API
Allowlist values
The <allowlist> controls which origins use the
feature:
*: all origins(): disabled entirelyself: same origin only"https://example.re": specific origin(self "https://a.example.re"): multiple origins
Example
In the following example, the server indicates the
geolocation feature shall be disabled in all
contexts.
Permissions-Policy: geolocation=()
In the following example, the server indicates the
encrypted-media feature shall be disabled for all
Origins except for report.example.re.
Permissions-Policy: encrypted-media=("https://report.example.re")
In the following example, the server indicates the
microphone feature shall be disabled for all
Origins except itself and those with
origin example.re.
Permissions-Policy: microphone=(self "https://example.re")
Blocking unload handlers to improve bfcache eligibility. This prevents third-party scripts and extensions from registering unload events degrading back-forward navigation performance.
Permissions-Policy: unload=()
Troubleshooting
Permissions-Policy violations appear silently in most cases, with the blocked feature returning a denied state or throwing an error without a visible browser prompt.
Feature blocked in an iframe due to missing
allowattribute. Even when the parent page permits a feature, embedded iframes need an explicitallowattribute to access the feature. Add the attribute to the iframe tag:<iframe src="..." allow="camera; microphone">. Without the attribute, the iframe receives a denied permission state regardless of the HTTP header policy.Geolocation, camera, or microphone not working after setting the policy. A policy like
Permissions-Policy: geolocation=()disables the feature for all origins, including the page itself. To allow the feature on the same origin only, usegeolocation=(self). To allow a specific embedded origin as well, usegeolocation=(self "https://maps.example.re"). The browser never prompts the user for a feature the policy has already denied.Wildcard
*granting less than expected. Every policy-controlled feature accepts the*allowlist, which makes the feature available to the document and to any origin it delegates to. The wildcard does not skip user consent: features like camera or geolocation still trigger the normal permission prompt. Cross-origin iframes also still need theallowattribute from item 1 before the wildcard applies to them. Check the browser console for warnings about unrecognized or unsupported allowlist values.Migrating from Feature-Policy to Permissions-Policy. The legacy Feature-Policy header uses a different syntax:
Feature-Policy: geolocation 'self'vs.Permissions-Policy: geolocation=(self). Browsers that support Permissions-Policy ignore Feature-Policy when both headers are present. Update the header name and convert the syntax: replace spaces with=, wrap origin lists in parentheses, and drop the single quotes aroundselfandnone(use()instead of'none').Debugging with
document.featurePolicy.allowsFeature(). In Chromium-based browsers, open the DevTools Console and rundocument.featurePolicy.allowsFeature('camera')to check whether a feature is allowed in the current context. This returnstrueorfalse. For iframe contexts, pass the origin as a second argument:document.featurePolicy.allowsFeature('camera', 'https://embed.example.re'). Firefox exposesdocument.featurePolicyonly behind thedom.security.featurePolicy.webidl.enabledpreference, so this debugging technique works by default in Chromium-based browsers.