Every page you serve can ask for the camera, the microphone, location, payment handlers and more — and so can every third-party frame you embed. Permissions Policy declares which of those your site actually uses and switches off the rest, with the browser reporting anything that tries.
A browser hands every document a large set of powerful features by default. Most sites use almost none of them, but the permission to ask is granted all the same — to your own pages, and to every cross-origin frame they embed. Injected script inherits that same surface. Narrowing it costs nothing in functionality if you were not using the feature, and removes an entire category of thing a compromise could attempt.
Camera, microphone, geolocation, payment handlers, USB, serial and more are reachable from any page unless you say otherwise. Nothing prompts you to narrow that list, so most sites carry the full surface indefinitely without ever deciding to.
Third-party iframes operate inside the permissions your page grants them. A widget, an advert or an embedded player can reach for features you never intended it to have, and the request goes to your visitor carrying your site's name.
The same open default applies to credential APIs. A cross-origin frame able to invoke WebAuthn from inside your page is a meaningful risk on any site where a passkey ceremony carries weight — and it is a permission, so it can be withdrawn.
One response header lists the features your site is permitted to use and who may use them. Report URI collects the violation reports, so you can see what your pages and their frames actually reach for before you enforce anything.
Each directive takes the form feature=(allowlist). An empty list switches the feature off for your page and every frame inside it; (self) keeps it for your own origin; naming an origin grants it to a specific third party and nobody else. You describe the shape of your site once and the browser enforces it on every request.
When something requests a feature your policy does not permit, the browser reports it — naming the feature, the frame that asked, and the page it happened on. That is frequently the first time a team discovers an embedded widget has been quietly requesting location or camera access on their site.
Learn more about the Reporting API →Send Permissions-Policy-Report-Only and the browser evaluates your policy and reports against it without withdrawing anything. You can write the restrictive policy you actually want on day one, watch what it would have affected, and enforce once the reports agree with your understanding of the site.
One header. No code. Violation reports start arriving from your first visitor.
30-day free trial · One header · No code · Cancel anytime
The syntax is compact and the behaviour follows from it. Knowing how a directive reads is most of knowing what your policy will do.
| Directive | What it means |
|---|---|
| camera=() | Switched off for your page and every frame inside it |
| microphone=(self) | Available to your own origin only, denied to embedded content |
| geolocation=(self "https://example.com") | Your origin plus one named third party, and nobody else |
| Permissions-Policy-Report-Only | The policy is evaluated and reported, but nothing is withdrawn |
| Permissions-Policy | The policy is enforced and violations are still reported |
| Feature-Policy | The predecessor header this specification replaced |
A feature you never listed keeps its browser default, so a policy is a list of decisions rather than an exhaustive inventory you have to complete before shipping.
Permissions Policy is a browser standard and the reporting is built in beside it. The browser evaluates your policy on every page load and reports over the Reporting API, so what you learn describes the frames your real visitors were served rather than the ones a crawler happened to reach.
Start in report-only and nothing is withdrawn. One header is the entire deployment, and our free builder will write it for you.
Permissions-Policy-Report-Only: camera=(), microphone=(),
geolocation=()
Reports travel over the Reporting API, so you will also need a Report-To group pointing at your Report URI endpoint — the exact header is on your Setup page. To enforce later, send the same directives as Permissions-Policy.
Our Permissions Policy builder lists every feature the standard defines, lets you set an allowlist for each, and produces the finished header. It also understands the legacy Feature-Policy syntax, so an older header can be pasted in and translated rather than rewritten by hand.
It is free, needs no account, and nothing you enter leaves your browser.
Permissions Policy governs which browser capabilities are reachable from your pages. It does not decide what code is allowed to load, and it does not tell you what that code contains — it is the capability layer, and it works alongside the rest.
| Permissions Policy does | Pairs with |
|---|---|
| Restricts powerful browser features | CSP for load control — deciding what is allowed to execute at all |
| Constrains what embedded frames may do | Frame Watch for frame inventory — knowing which frames are there in the first place |
| Protects credential ceremonies from frames | Passkeys Protection for the authentication case in full |
| Reports what was requested and by whom | Script Watch for dependency visibility — knowing whose code did the asking |
Together, these form the browser-native security layer that sits between your application and the code executing around it.