Geodocs.dev

Permissions-Policy Header Behavior for AI Crawlers

ShareLinkedIn

Open this article in your favorite AI assistant for deeper analysis, summaries, or follow-up questions.

Permissions-Policy is an HTTP response header that allows a site to declare which browser features its documents and embedded iframes may use. AI crawlers that perform headless renders inherit the same enforcement semantics as browsers, so a tight policy can silently break the hydration and content extraction that AI search engines depend on to cite a page.

TL;DR

Use Permissions-Policy to gate features such as geolocation, camera, microphone, clipboard-read, and the newer browsing-topics directive. Default-deny policies are safe for sensitive features but should leave script-execution adjacent features alone, because AI crawlers run headless renders before extracting content. Migrate any remaining Feature-Policy headers to Permissions-Policy syntax—per MDN's Permissions-Policy reference and the W3C Permissions Policy Working Draft, the new header is the successor and uses a structured-fields list grammar.

Definition

Permissions-Policy is an HTTP response header defined by the W3C Permissions Policy specification (Working Draft, October 2025). It supersedes the legacy Feature-Policy header and uses a structured-fields list grammar where each directive is a feature name followed by an allowlist:

Permissions-Policy: geolocation=(), camera=(self), browsing-topics=()

Each allowlist value can be * (any origin), self (same-origin), () (none), or one or more quoted origins. The header's policy applies to the document it returns and is inherited by embedded iframes unless the iframe carries its own allow attribute. A companion header, Permissions-Policy-Report-Only, exists for staged rollout and reports violations without enforcing them.

Permissions-Policy is similar in shape to Content Security Policy but controls browser-feature access rather than resource loading. Browsers that honor the policy will return a NotAllowedError from blocked APIs; non-supporting browsers ignore the header silently.

Why this matters

AI search engines and answer engines do not just fetch HTML. Most modern crawlers—including Googlebot, GPTBot, PerplexityBot, ClaudeBot, and Bing's crawlers—run a headless rendering pass to evaluate JavaScript and extract the rendered DOM. That headless renderer enforces Permissions-Policy the same way a normal browser does. A policy that disables a feature your hydration depends on (for example, an analytics SDK that reads navigator.userAgent data via the client-hints directive, or a third-party widget that relies on clipboard-read for embedded examples) can cause silent JavaScript errors that break extraction.

The practical effect is twofold: pages with overly restrictive Permissions-Policy settings can render an empty or partial DOM to the AI crawler, which translates into missing citations, and pages with too-permissive policies expose iframe content to features they should not have. The right answer is to reason about each directive on its merits, not to default-deny everything because security tooling suggests it.

Directive reference (AI-relevant subset)

DirectiveDefaultAI crawler impactRecommended policy
geolocation() (deny)Low — no AI crawler requests location.Keep () unless your page needs it.
camera, microphone()Low — not used by crawlers.Keep ().
clipboard-read, clipboard-write()Medium — some embedded code-sample widgets depend on these.(self) if widgets need them, else ().
browsing-topics*High — controls Topics API access; crawlers that read topical signals are affected.(self) for tighter control, () to opt out completely.
interest-cohort (FLoC)*Deprecated; safe to set ().().
language-detector, translator*Medium — used by experimental Translator/Language Detector APIs in the headless pass.(self) if you use them, else ().
web-share(self)Low.Keep default.
encrypted-media(self)Low.Keep default unless you embed DRM iframes.
fullscreen(self)Low.Keep default.
accelerometer, gyroscope, magnetometer()Low.Keep ().

The full directive list is enumerated by MDN's Permissions-Policy reference. Directives evolve—browsing-topics and language-detector were added relatively recently—so audit the active list against the W3C draft annually.

Migration from Feature-Policy

The legacy Feature-Policy header used a different syntax (Feature-Policy: geolocation 'none') and was deprecated by the W3C and Chrome in 2020. Both Scott Helme and HTTP Toolkit documented the migration. The structured-fields grammar in Permissions-Policy differs in three ways: feature names use hyphenation (geolocation vs geolocation), allowlists use parentheses with quoted origins, and combining multiple directives uses comma separation rather than semicolons. Keep Feature-Policy only if you still serve traffic to user agents that have not implemented the successor.

Practical application

A reasonable starter policy for a content site that wants to remain AI-search friendly:

Permissions-Policy: geolocation=(), camera=(), microphone=(), accelerometer=(), gyroscope=(), magnetometer=(), payment=(), usb=(), browsing-topics=(self), interest-cohort=()

A five-step rollout:

  1. Inventory features used. Audit your front-end and third-party widgets to list every browser feature they call.
  2. Stage with Permissions-Policy-Report-Only. Deploy the candidate policy in report-only mode and collect violation reports from your real browsers and your headless test pipeline.
  3. Run an AI-crawler simulation. Render the page in a headless Chromium with the new policy applied; confirm the DOM hydrates fully and your structured data renders.
  4. Promote to enforcing mode. Replace Permissions-Policy-Report-Only with Permissions-Policy.
  5. Re-validate quarterly. Re-audit when adding new third-party widgets, when the W3C publishes new directives, or when AI crawlers update their render stack.

Common mistakes

  • Default-denying every directive. A blanket *=() style policy can disable features your own hydration relies on. Reason directive-by-directive.
  • Forgetting iframe allowlists. Embedded