FreeToGenerate.com

One specification writes the same policy two different ways. Paste either and get the other, with every difference between the two grammars named. Nothing is uploaded.

Try one:
Starting from

The value of the attribute, without the attribute name or the quotes around it.

The same policy, both ways

What the parser found

  • fullscreen This feature has no allowlist. The specification says an empty allowlist in an attribute defaults to 'src', so it has been written out explicitly above.

Before you paste the header

  • This policy uses 'src', which has no effect in a header. There is no header spelling of “the origin of whatever this iframe loads”, because a header is not attached to an iframe.

What changed between them

One specification serialises this policy twice, in two grammars. Four things differ, and a hand conversion usually gets at least one of them wrong.

  1. Keywords are quoted in the attribute and bare tokens in the header, and origins are the other way round: bare in the attribute, quoted strings in the header.
  2. Directives are separated by a semicolon in the attribute and by a comma in the header, because the header is a Structured Fields dictionary.
  3. Blocking a feature is the keyword 'none' in the attribute and an empty pair of brackets in the header.
  4. And the dangerous one: a feature written with no allowlist at all means opposite things. In a header, empty brackets mean nobody. In an attribute, a bare feature name defaults to 'src', which is the framed page's own origin.

One more thing worth knowing

The specification cites RFC 8941 for the header's grammar, and RFC 9651 replaced that document in 2024. The replacement adds two data types this header does not use and moves the grammar to an informative appendix; it changes nothing about dictionaries, tokens or bracketed lists. So the citation is out of date and the behaviour is not.

Everything here runs in your browser. Nothing you enter is uploaded.

Also available in: Español · Português · Français · العربية

Permissions-Policy converter: header and iframe allow attribute

Convert a policy between its two spellings, and see exactly what changes between them.

What is Permissions Policy?

Permissions Policy is how a page says which browser features it and the things it embeds are allowed to use — the camera, the microphone, geolocation, fullscreen, payment requests and a few dozen others. It replaced Feature Policy, and it is delivered two ways: as a Permissions-Policy response header covering the whole document, and as an allow attribute on an individual iframe covering just that frame.

Both are defined in the same W3C specification, and both express the same idea: a feature name, followed by a list of origins that may use it. What is easy to miss is that the specification serialises that list in two different grammars, one for each delivery mechanism, and they do not look alike.

This converter takes either spelling and produces the other, then names every difference it applied. It is a translation tool rather than a policy generator: it does not decide what your policy should be, and it takes no view on which features you ought to restrict.

How to use it

  1. Say which spelling you are starting from. An iframe allow attribute, or a Permissions-Policy header value. The parser follows the grammar for whichever you pick, so a header pasted as an attribute will be reported as wrong rather than quietly accepted.
  2. Paste the value on its own. Without the attribute name, the surrounding quotes, or the header's field name and colon — just what sits inside. The sample buttons load five policies, each chosen to show a different part of the two grammars.
  3. Read both outputs and the three panels under them. One panel lists what the parser found in your input. One lists anything that will not survive the trip into a header. And one names the four ways the two grammars differ, so you can see which of them applied to your policy.

Four ways the two grammars differ

Section 5.1 of the specification gives the attribute an ABNF grammar of its own; section 5.2 says the header is a Structured Fields dictionary instead. The result is that `allow="geolocation 'self' https://example.com"` and `Permissions-Policy: geolocation=(self "https://example.com")` are the same policy written two ways, and four things change between them.

The quoting inverts. Keywords are quoted in the attribute and bare in the header; origins are the other way round, bare in the attribute and quoted strings in the header. The separator changes too: a semicolon between directives in the attribute, a comma in the header, because a dictionary's members are comma-separated. And blocking a feature is the keyword none in the attribute but an empty pair of brackets in the header — the word does not appear in a header at all.

The fourth is the one worth being careful about, because it silently reverses the meaning rather than failing. A feature written with nothing after it means opposite things in the two grammars. Empty brackets in a header are a list of no origins: nobody. A bare feature name in an attribute is not empty at all — section 5.1 says the allowlist then defaults to 'src', which is the origin of whatever that iframe loads. Convert one to the other without noticing and a blocked feature becomes an allowed one.

Honest limitations

There is one thing an attribute can say that a header cannot. The keyword 'src' means the origin of the document in the iframe's src attribute, and a response header is not attached to an iframe, so there is nothing for it to refer to. The specification is subtle here and worth reading carefully: section 4 says the keyword can appear in the text of allowlists in headers and attribute strings, so it is not a syntax error, and section 9 only resolves it when a target origin is given. In a header it parses and then does nothing. This tool reports that as a loss rather than as an error, because that is what the specification describes.

The same shape applies to feature names. Section 5.2 says that if a dictionary member does not name a feature the browser supports, the member is ignored by the processing steps. A typo in a header does not produce a warning anywhere; the directive simply has no effect. This converter checks that a name is spelled legally — letters, digits and hyphens — but it deliberately does not carry a list of supported features, because that list differs between browsers and versions and a stale copy would be worse than none.

One more thing worth knowing. The specification cites RFC 8941 for the header's grammar, and RFC 9651 replaced that document in 2024. The replacement adds two data types this header does not use, moves the grammar to an informative appendix and refines how parse failures are handled; it changes nothing about dictionaries, tokens or bracketed lists. So the citation is out of date and the behaviour is not — which is worth saying in full, because either half on its own is misleading.

Why is it free?

It is two small parsers and two serialisers, and your browser runs them as you type. No server is involved, so there is nothing to meter and no account to create.

Nothing is uploaded. The policy you paste stays in this tab.