🧭 Permissions-Policy Builder

Pick None to block a browser feature entirely, Self to allow it only for your own origin, or leave Default to omit that feature from the policy.

The syntax it writes

Each feature you set becomes name=(allowlist), comma-separated, assembled in your browser. The three choices map to:

camera=()          None    - blocked for everyone, your own page included
camera=(self)      Self    - your origin may use it, embedded frames may not
(omitted)          Default - the browser's own default applies

An allowlist can name other origins, and they must be quoted: geolocation=(self "https://maps.example.com") - space separated inside the parentheses, commas only between features. That is the newer structured syntax; the retired Feature-Policy header used geolocation 'self' with semicolons, so old snippets will not parse.

What blocking actually does

A feature denied at the top level cannot be handed back further down. Frames inherit a policy that only ever narrows.

Frequently asked questions

Why can't my embedded video go fullscreen any more?

Because fullscreen=(self) excludes the player's origin. Name it in the allowlist - fullscreen=(self "https://www.youtube.com") - and keep allow="fullscreen" on the iframe.

Is Permissions-Policy the same as Feature-Policy?

It is the same idea with a new name and incompatible syntax. Browsers dropped support for the old header, so anything still sending Feature-Policy is sending a header nothing reads.

Does this replace asking the user?

No, it sits in front of the prompt. The user's own decision still applies to anything you allow; the header only removes features from the table beforehand.