Gating powerful browser features
The Permissions-Policy header (formerly Feature-Policy) lets a site
declare which powerful browser features — geolocation, camera, microphone,
payment, fullscreen and many more — may be used, and in which origins and
frames. This reference lists the common features with their default allowlists
and explains the structured syntax and iframe delegation.
How it works
Each feature is assigned an allowlist of origins permitted to use it. In Permissions-Policy structured syntax the allowlist is wrapped in parentheses:
Permissions-Policy: geolocation=(self "https://maps.example.com"), camera=(), fullscreen=*
The tokens are * (any origin), self (the document’s own origin), an
explicit quoted origin list, or an empty list () to disable the feature
everywhere. A cross-origin <iframe> can request a feature with
allow="geolocation", but it is granted only if the parent’s policy already
permits that origin — the header sets the ceiling, the allow attribute
delegates beneath it.
Tips and notes
- Disable unused powerful features with
feature=()as a defence-in-depth step. selfis stricter than*: it excludes cross-origin frames unless explicitly delegated.- Combine the header with the iframe
allowattribute to scope features to specific embeds. - Permissions-Policy uses parentheses; the legacy Feature-Policy used space-separated origins without them.
- Browser support varies per feature — verify the specific feature in your target browsers.
Common features and sensible defaults
| Feature | Default allowlist | Suggested policy |
|---|---|---|
camera | self | () unless your site uses video chat |
microphone | self | () unless your site uses audio input |
geolocation | self | (self) or () depending on need |
payment | self | (self) only; never * |
fullscreen | self | (self) for media sites; () elsewhere |
autoplay | * | (self) to prevent third-party autoplay |
usb | self | () unless Web USB is required |
clipboard-read | self | () for most sites |
clipboard-write | self | (self) if you have copy-to-clipboard UX |
Relationship to the Content-Security-Policy header
Permissions-Policy and Content-Security-Policy (CSP) are complementary but distinct. CSP controls which scripts, styles, and resources can load and execute on your page. Permissions-Policy controls which browser capabilities the page and its frames can invoke. A page can have a tight CSP that blocks inline scripts while still having an unrestricted geolocation policy, or vice versa. Both headers should be set in a complete browser security hardening strategy; this reference covers Permissions-Policy only.
Iframe delegation in depth
When you embed a third-party widget — a map, a video player, a payment form — you need to think about which features it should be allowed to access. The Permissions-Policy header on your page sets the ceiling: if your header says camera=(), no frame on the page can access the camera, regardless of what its allow attribute requests.
If your header permits camera=(self "https://video.partner.com"), then a frame from video.partner.com can additionally request camera access via allow="camera" on the <iframe> element. The frame only receives access if both conditions are met: it is a permitted origin in the header, and the allow attribute is present on the element. This two-level gate prevents frames from escalating permissions that the parent page has not explicitly approved.