The Permissions-Policy header lets a site declare which powerful browser features — camera, microphone, geolocation, fullscreen and more — are available to itself and to the frames it embeds. Formerly called Feature-Policy, it is a defence-in-depth control: even if a script or third-party iframe tries to use a sensitive API, the policy can deny it before the user is ever prompted. This reference lists the standard features with their default allowlist and the syntax to configure them.
How it works
A policy is a comma-separated list of feature=allowlist entries sent in the Permissions-Policy response header. Each allowlist is one of: * (all origins), () (no origin at all), self (the document’s own origin), or a parenthesised set of specific origins. When you set nothing, each feature uses its spec default — usually self, occasionally * for low-risk features like picture-in-picture.
For embedded content there are two gates: the parent’s policy must delegate the feature to the frame’s origin, and the <iframe> must request it with an allow attribute. Both must agree, and the browser’s normal permission prompt still applies on top.
Why Permissions Policy matters for security and privacy
Even if you trust your own first-party scripts, a page typically embeds dozens of third-party resources: analytics, advertising, embedded maps, support widgets. Any of those could, if not constrained, attempt to access the camera, microphone, or geolocation — whether by accident, misconfiguration, or compromise. Permissions Policy closes those vectors before code even runs, providing a hard boundary that a Content Security Policy (which governs resource loading) does not cover.
It is also a signal of trustworthiness to users and auditors. A site that sends a restrictive Permissions-Policy header alongside a solid CSP demonstrates it has thought about the attack surface of its embedded content — increasingly expected in regulated industries and GDPR compliance reviews.
Feature-Policy migration
Feature-Policy used a different syntax — space-separated allowlists inside single quotes — and is now deprecated. If you are migrating old headers, note that Feature-Policy: camera 'self' becomes Permissions-Policy: camera=(self). Some browsers honour both during the transition, but you should not rely on that.
Tips and examples
A typical hardening header that locks down sensors and delegates only what is needed:
Permissions-Policy: geolocation=(self), camera=(), microphone=(),
payment=(self "https://checkout.example.com"), fullscreen=(self)
To grant a feature to an embedded frame, pair the header delegation with the iframe attribute:
<iframe src="https://maps.example.com"
allow="geolocation 'src'"></iframe>
Remember the empty list () is the strongest setting — it disables the feature for everyone, including your own scripts. Start strict and delegate deliberately rather than leaving sensitive features on their permissive defaults.
Recommended hardening baseline for most sites: disable camera, microphone, and payment for all origins; allow geolocation for self only; leave fullscreen as self. Extend deliberately for each embedded tool that genuinely needs a feature.