Permissions-Policy header

Turns browser features such as camera, microphone, geolocation and payment off for your page and anything it embeds.

Updated 3 November 2026

Check your site's Permissions-Policy header

We send one normal request (following redirects) and grade the Permissions-Policy header on the final response.

Recommended value

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()
Value / directiveWhat it does
feature=() Disabled for this page and all frames.
feature=(self) Allowed for your own origin only.
feature=(self "https://maps.example") Allowed for your origin and one named third party. Origins go in double quotes.
feature=* Allowed everywhere. Rarely what you want.

What it protects

Every iframe and third-party script on your page could ask the visitor for powerful permissions: camera, microphone, location, USB devices, payment. If an ad network or compromised widget does it, the prompt appears on your domain. Permissions-Policy lets you switch off what you never use, so those prompts can never appear.

Syntax

The header is a comma-separated list of feature=(allowlist) entries:

Permissions-Policy: camera=(), microphone=(), geolocation=(self), payment=(self "https://checkout.example")

() means nobody, self means your origin, quoted URLs add other origins. You can also delegate a feature to one iframe with the allow attribute: <iframe allow="geolocation">.

Permissions-Policy vs Feature-Policy

Feature-Policy was the earlier draft and used a different syntax (camera 'none'). Current browsers read Permissions-Policy. If you still send Feature-Policy, replace it rather than relying on it.

Which features to list

Disable what you do not use: camera, microphone, geolocation, payment, usb, serial, bluetooth, display-capture. Browsers log a console warning for feature names they do not recognise, which is harmless.

How to set Permissions-Policy

nginx

# inside your server { } block
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()" always;

Apache

# .htaccess or virtual host (needs mod_headers)
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"

Laravel middleware

// app/Http/Middleware/SecurityHeaders.php
public function handle(Request $request, Closure $next): Response
{
    $response = $next($request);
    $response->headers->set('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=(), usb=()');

    return $response;
}

// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\App\Http\Middleware\SecurityHeaders::class);
})

Express (Node.js)

app.use((req, res, next) => {
  res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=(), usb=()');
  next();
});

// or: app.use(require('helmet')()) for a sensible default set

Cloudflare

Rules → Transform Rules → Modify Response Header → Create rule.
Match: all incoming requests (or your hostname).
Then: Set static → Header name: Permissions-Policy → Value: camera=(), microphone=(), geolocation=(), payment=(), usb=()

In nginx, an add_header inside a location block discards every add_header inherited from the server block. Repeat your security headers there, or use an include file. The always flag also sends the header on error responses.

Common mistakes

  • Using the old Feature-Policy syntax (camera 'none') in a Permissions-Policy header. It does not parse.
  • Leaving origins unquoted, as in geolocation=(self https://maps.example).
  • Disabling a feature your own checkout or video page needs. Allow self on those routes instead.
  • Copying interest-cohort=() from old guides. It was for FLoC, which Chrome dropped.

FAQ

What is the difference between Permissions-Policy and Feature-Policy?

Permissions-Policy is the current standard and uses feature=(allowlist) syntax. Feature-Policy was the earlier version with a different syntax.

Is Permissions-Policy required?

No, but it is a quick way to cut off camera, microphone and location prompts from embedded third-party content.

Headers are one of 30+ things attackers check

The free StackShield scan also checks for exposed .env files, debug mode, leaked tooling, weak TLS and more, from the outside, in about a minute.

Run a free scan