The problem: too many browser features
Modern browsers can do a lot: query geolocation, use microphone/camera, read motion sensors, address USB and Bluetooth devices, set FLoC tracking cohorts, vibrate, toggle fullscreen. By default these features are available — if an embedded iframe or a third-party script tries to access them, the browser at best prompts the user (e.g. "Allow microphone?"), and at worst (FLoC) doesn't even ask.
With the Permissions-Policy (formerly called Feature-Policy) you can disable these features centrally. Even if an embedded iframe or script tries to open the microphone, the browser blocks it without prompting. This reduces the attack surface and is an important privacy lever.
Header structure
General form:
Permissions-Policy: feature1=(allowlist), feature2=(allowlist), ...
The allowlist can be:
()— empty, nobody may use the feature.(self)— only your own origin, not embedded iframes.(self "https://partner.com")— your own origin and exactly one external one.(*)— all origins. Not recommended.
Recommended default for most sites
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=(), usb=(), bluetooth=(), magnetometer=(), gyroscope=(), accelerometer=(), midi=(), xr-spatial-tracking=(), interest-cohort=()
This locks down all exotic and privacy-sensitive features completely. Browsers that don't recognize the directives silently ignore them — no risk from unknown values.
The most important features
geolocation— GPS / location API.camera,microphone— getUserMedia.payment— Payment Request API (Apple Pay, Google Pay).usb,bluetooth— direct hardware access.magnetometer,gyroscope,accelerometer— motion / orientation sensors (privacy-relevant: can be abused for fingerprinting).midi— MIDI hardware (rarely needed, but enabled by default).interest-cohort— Google's FLoC tracking. Use()to opt out.autoplay— automatic playback of video / audio.fullscreen— request to fullscreen.picture-in-picture— picture-in-picture mode.clipboard-read,clipboard-write— clipboard access.
When to enable a feature
If your site truly needs a feature — e.g. geolocation for a store finder or camera for a
QR code tool — only enable your own origin:
geolocation=(self). This prevents
embedded third-party pages from gaining access.
Configuration examples
nginx (compact):
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), bluetooth=(), magnetometer=(), gyroscope=(), accelerometer=(), midi=(), interest-cohort=()" always;
Apache:
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=(), ..."
Browser support
Chrome, Edge, and Opera have fully understood Permissions-Policy since around 2021.
Firefox accepts the header directives in part but handles overriding features in iframes
via the allow=... attribute
differently. Safari is catching up gradually. Since the header is ignored when not
understood, setting it is risk-free — even if the protection then only takes effect in
some browsers.