Permissions-Policy Header BuilderChoose, per powerful browser feature, whether to block it everywhere, allow it only on your own origin, or allow a short list of origins. This tool turns those toggles into a valid, copyable Permissions-Policy header, with ready to paste Nginx and Apache snippets and an Express note.
For each feature pick Off for an empty allowlist () that blocks it everywhere, Self for (self) to allow only your own origin, or Origins to type a space separated allowlist. Features default to a locked down baseline. A feature you leave at Off is denied for every frame.
Permissions-Policy header doesThe Permissions-Policy header is a response header that tells the browser which powerful features a page, and any frames it embeds, are allowed to use. A directive names a feature and gives it an allowlist of origins. For example geolocation=() blocks the geolocation API for everyone, camera=(self) allows the camera only on your own origin, and payment=(self "https://acme.example") allows the payment request flow on your origin plus one named partner. The mechanism follows the allowlist model in the Permissions Policy specification, and the per feature names line up with the current MDN reference.
The single most useful pattern is the empty allowlist. Writing a feature name followed by an empty pair of parentheses, like microphone=(), blocks that feature for every origin in the document tree, including your own page and every embedded frame. It is the right default for any feature your site does not use. If a third party script or an injected iframe tries to call that API, the browser refuses, so the header shrinks what hostile content embedded in your page can reach. This is a containment layer that pairs well with a strict Content Security Policy.
When your own page genuinely needs a feature, use (self) so it works on your origin but stays blocked in cross origin frames. When a named partner needs it inside a frame you embed, add their exact origin in quotes, as in (self "https://acme.example"). Avoid the wildcard *: it allows the feature for every origin, including any frame anyone can get onto your page, which gives away the control the header was meant to provide. This tool never emits a bare wildcard, and warns if a feature is left wide open.
A directive you leave out of the header is not denied. The browser falls back to that feature default, which for most powerful features means allowed for the same origin and blocked for cross origin frames. So to actually deny a feature you must name it with an empty allowlist; relying on defaults leaves it on for your own origin. That is why a hardened baseline lists every feature it wants off rather than trusting the defaults, and why this builder starts from a locked down set you can loosen where you really need a feature.
Permissions-Policy replaces Feature-PolicyThe Permissions-Policy header is the successor to the older Feature-Policy header. They cover the same ground but the syntax differs: Feature-Policy used a space separated form like geolocation 'self', while Permissions-Policy uses the structured allowlist form like geolocation=(self). Feature-Policy is deprecated, so this tool only generates Permissions-Policy and never the legacy header. If you still send Feature-Policy for very old browsers, keep it as a separate legacy line and do not expect the two to share syntax.
A generated header is a strong starting point, not a finished one, because the right set of allowances depends on exactly what your pages and embedded frames do. Set it, then click through any flow that uses a camera, a microphone, location, or payment, and confirm nothing you need silently broke. When you have a candidate, paste your full response into the Security Headers and CSP Analyzer to see it alongside your other headers. Reasoning about whether a feature lockdown genuinely fits how an app embeds third parties, rather than pattern matching one string, is the kind of judgement an AI security testing approach is built for.