Permissions-Policy Header Generator

Build a correct Permissions-Policy HTTP header. Allowlist or block 30+ browser features (camera, microphone, geolocation, clipboard, USB, payment, fullscreen…) and copy ready-to-paste Nginx, Apache, Express, or CDN snippets.

Quick Presets

Features (33)

Sensors

accelerometer

Motion sensor data.

ambient-light-sensor

Ambient light reading.

gyroscope

Device gyroscope data.

magnetometer

Magnetic field data.

Media

camera

Access to camera devices.

microphone

Access to microphones.

autoplay

Auto-playing audio/video.

display-capture

Screen capture / getDisplayMedia().

encrypted-media

Encrypted Media Extensions (DRM).

fullscreen

Element.requestFullscreen().

picture-in-picture

Picture-in-picture for video.

speaker-selection

Choose which audio output to use.

screen-wake-lock

Keep the screen on with Wake Lock API.

Identity

geolocation

navigator.geolocation.

idle-detection

Idle Detection API.

publickey-credentials-create

WebAuthn credential creation.

publickey-credentials-get

WebAuthn credential retrieval.

otp-credentials

WebOTP API for SMS one-time passwords.

Storage

clipboard-read

Read from the clipboard.

clipboard-write

Write to the clipboard.

storage-access

Storage Access API for cross-site cookies.

Hardware

usb

WebUSB device access.

serial

Web Serial API.

hid

WebHID API.

midi

Web MIDI API.

gamepad

Gamepad input.

battery

Battery Status API.

xr-spatial-tracking

WebXR head/hand tracking.

window-management

Multi-screen Window Management API.

Other

payment

Payment Request API.

web-share

navigator.share().

browsing-topics

Topics API for interest-based ads.

cross-origin-isolated

Cross-origin isolation (SharedArrayBuffer).

Output

Header Value

accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()

Full HTTP Header

Permissions-Policy: accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()

Nginx

add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()" always;

Apache (.htaccess)

Header set Permissions-Policy "accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()"

Express / Node.js

res.setHeader('Permissions-Policy', 'accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()');

Cloudflare Page Rule

# Cloudflare Page Rule / Transform Rule
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()

HTML <meta> tag

<meta http-equiv="Permissions-Policy" content="accelerometer=(), ambient-light-sensor=(), gyroscope=(), magnetometer=(), camera=(), microphone=(), autoplay=(), display-capture=(), encrypted-media=(), fullscreen=(), picture-in-picture=(), speaker-selection=(), screen-wake-lock=(), geolocation=(), idle-detection=(), publickey-credentials-create=(), publickey-credentials-get=(), otp-credentials=(), clipboard-read=(), clipboard-write=(), storage-access=(), usb=(), serial=(), hid=(), midi=(), gamepad=(), battery=(), xr-spatial-tracking=(), window-management=(), payment=(), web-share=(), browsing-topics=(), cross-origin-isolated=()" />

About the Permissions-Policy Header Generator

The Permissions-Policy Header Generator builds the HTTP Permissions-Policy response header — the W3C-standard way to allow, restrict, or completely block specific browser features on your site and any iframes embedded within it. Each known feature is exposed as a four-state toggle (Block / Self / All / Custom origins) and the final header updates live as you change it.

Permissions-Policy is a defense-in-depth security and privacy header. It does not prevent malicious code from running, but it does let you tell the browser "even if some script tries to call navigator.geolocation or open the camera, deny that access at the platform level." It is also the only practical way to neuter cookieless tracking surfaces like browsing-topics and interest-cohort across your entire site.

This generator runs entirely in your browser. Nothing is uploaded — your feature list, origins, and tweaks stay on your device.

Allowlist Cheat Sheet

AllowlistMeaning
()Empty allowlist — feature is fully disabled, including for the page itself.
(self)Allowed only on the document's own origin (and same-origin iframes). The most common safe default.
*Allowed for every origin, including any iframe. Use sparingly — equivalent to "no restriction."
(self "https://x.com")Allowed for the page itself plus the listed origins. Origins must be quoted strings.

How to Use the Permissions-Policy Header Generator

  1. Pick a Quick Preset matching your site type (lock-down baseline, marketing site, WebRTC app, maps app), or build a header from scratch.
  2. For each feature, click one of the four mode pills: Block () empties the allowlist, Self restricts to the page's own origin, All (*) opens it to every origin, and Custom lets you list specific origins.
  3. When you choose Custom, type a space- or comma-separated list of origins in the input that appears below — for example self https://maps.google.com. The tool quotes origins automatically.
  4. Watch the Header Value banner update live. Use the All Block / All Self / Reset buttons at the top to apply a single mode to every feature in one click.
  5. Copy the value or pick a server-specific snippet (Nginx add_header, Apache Header set, Express res.setHeader, Cloudflare Page Rule, or HTML <meta>).
  6. Verify the live header in DevTools → Network → your document → Response Headers, or in chrome://settings/content's per-site permissions UI.

Frequently Asked Questions

What is the difference between () and not listing the feature at all?

() explicitly disables the feature for everyone, including the top-level document. Omitting the feature falls back to the browser's default policy, which for most features is self — meaning the page can use it but cross-origin iframes cannot. If you really want to opt out, use ().

Permissions-Policy vs Feature-Policy — which one do I send?

Feature-Policy is the deprecated 2018-era predecessor. It used a different syntax (geolocation 'none' instead of geolocation=()). All modern browsers honour Permissions-Policy — send only that. Don't send both, and never send Feature-Policy by itself.

Does the HTML <meta> tag actually work?

Partially. A <meta http-equiv="Permissions-Policy"> tag is honoured by Chromium-based browsers but only supports allowlists that don't include cross-origin URLs (so self works, "https://example.com" does not). The HTTP response header is the only fully-supported delivery mechanism — use <meta> only as a fallback when you cannot change server config.

What about iframe allow= attributes?

Iframes use a related but different mechanism: <iframe allow="camera; microphone"> grants those features to the embedded document, but only up to the limits set by the parent page's Permissions-Policy. The header is the upper bound; the iframe attribute is the per-frame opt-in. This generator produces the parent header — once that allows self, you can hand specific iframes the ability to use the feature via allow.

What is browsing-topics and should I block it?

Topics is part of Chrome's Privacy Sandbox — it lets sites infer interest categories about the user. Many sites disable it via browsing-topics=() to opt out of contributing data to advertisers. The "Lock everything down" preset blocks it by default.

Why is my getUserMedia() failing after I added the header?

The most common reason: you set camera=() or microphone=() instead of camera=(self). The empty allowlist blocks the feature even on your own origin. Switch to Self for any feature your top-level page actually uses.

Is data sent to a server?

No. The generator runs entirely in your browser; everything you type stays on your device. There is no signup, no telemetry, and no upload.