Skip to main content

Content Security Policy Parser and Checker API

REAL DATA

Parse a Content-Security-Policy and see whether a URL would be allowed or blocked, which directive decided, and the whole default-src fallback chain.

Authoritative reference data or standards computation

Base URL
/api/csp
Capabilities
5 routes
Last updated
July 30, 2026
Data sources · 6
+3 more

GET /api/csp/check

Walks the CSP3 fallback chain for the request's destination, runs the pre-request check of the directive that executes, and reports allowed, blocked or ambiguous plus the expression that matched. Evaluates the policy you paste — it never fetches your origin and never fetches the resource.

Live requestRuns against the public API
No key required
GET/api/csp/check?policy=script-src+%27nonce-r4nd0mB4se64Value1234567%27+%27strict-dynamic%27&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com

Request parameters

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

The absolute URL being loaded, parsed with the WHATWG URL parser (up to 2048 characters). A relative reference is a 400: CSP matches the request's already-resolved URL. Credentials in the URL are rejected and never echoed. To model a redirect chain, pass the final URL and set 'redirectCount'.

The protected document's origin as scheme://host[:port], with no path, query, fragment or trailing slash. It is serialized the way a browser serializes an origin — scheme and domain lowercased, IPv6 literal compressed, default port dropped — and the serialization is written back into meta.params. Required, not optional: the origin decides 'self' and also whether a schemeless host-source may match the resource's scheme (§6.7.2.8), so guessing it from 'resource' would silently manufacture matches. The literal 'null' opaque origin is rejected.

What is being loaded. The 22 Fetch request destinations are mapped to an effective directive by §6.8.1 — 'empty' models Fetch's empty destination (fetch(), XMLHttpRequest, WebSocket, EventSource, sendBeacon) — and the three remaining values run a different check: 'base-uri' (§6.3.1.1, redirect count forced to 0), 'form-action' (§6.4.1.1) and 'frame-ancestors' (§6.4.2.1, where 'resource' is read as one ancestor document's URL). It is a destination, not a directive name: pass 'script', and §6.8.1 resolves it to script-src-elem.

The request's parser metadata. true models a <script src> written in the HTML or produced by document.write(); false models a script element created by document.createElement. It flips the answer whenever a script directive contains 'strict-dynamic' (§6.7.1.1) and is ignored otherwise — and it defaults to true, so leaving it out models the parser-inserted case.

The element's nonce attribute, i.e. the request's cryptographic nonce metadata. Compared byte-for-byte with each nonce-source's base64-value (§6.7.2.3) — case-sensitive, no decoding. Consulted only by the script and style directives' pre-request checks (§6.7.1.1, §6.1.13.1, §6.1.14.1); ignored with a warning for any other effective directive. The base64-value grammar admits '+', which a query string reads as a space, so percent-encode it as %2B here and in 'policy'.

The element's integrity attribute. Per §6.7.2.4 every hash in the metadata must be listed as a hash-source in the directive for the request to be allowed; the comparison is algorithm plus base64 string equality, with base64url and base64 treated as equivalent, so no hashing happens. Consulted only by the script element directives; ignored with a warning otherwise.

The request's redirect count. When it is not 0, §6.7.2.8 skips path matching entirely — a deliberate compromise against cross-origin path leaks (§7.6).

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com"
const res = await fetch("https://randomapi.dev/api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 10
policy string required

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

allowed: 1 – 4096
example: policy=default-src 'self'; script-src 'nonce-r4nd0mB4se64Value1234567' 'strict-dynamic'
resource string required

The absolute URL being loaded, parsed with the WHATWG URL parser (up to 2048 characters). A relative reference is a 400: CSP matches the request's already-resolved URL. Credentials in the URL are rejected and never echoed. To model a redirect chain, pass the final URL and set 'redirectCount'.

allowed: 1 – 2048
example: resource=https://cdn.example.com/app.js
self string required

The protected document's origin as scheme://host[:port], with no path, query, fragment or trailing slash. It is serialized the way a browser serializes an origin — scheme and domain lowercased, IPv6 literal compressed, default port dropped — and the serialization is written back into meta.params. Required, not optional: the origin decides 'self' and also whether a schemeless host-source may match the resource's scheme (§6.7.2.8), so guessing it from 'resource' would silently manufacture matches. The literal 'null' opaque origin is rejected.

allowed: 1 – 256
example: self=https://example.com
context enum

What is being loaded. The 22 Fetch request destinations are mapped to an effective directive by §6.8.1 — 'empty' models Fetch's empty destination (fetch(), XMLHttpRequest, WebSocket, EventSource, sendBeacon) — and the three remaining values run a different check: 'base-uri' (§6.3.1.1, redirect count forced to 0), 'form-action' (§6.4.1.1) and 'frame-ancestors' (§6.4.2.1, where 'resource' is read as one ancestor document's URL). It is a destination, not a directive name: pass 'script', and §6.8.1 resolves it to script-src-elem.

default: script
allowed: script | xslt | audioworklet | paintworklet | style | image | font | audio | video | track | frame | iframe | object | embed | manifest | worker | serviceworker | sharedworker | empty | json | text | webidentity | base-uri | form-action | frame-ancestors
example: context=iframe
parserInserted boolean

The request's parser metadata. true models a <script src> written in the HTML or produced by document.write(); false models a script element created by document.createElement. It flips the answer whenever a script directive contains 'strict-dynamic' (§6.7.1.1) and is ignored otherwise — and it defaults to true, so leaving it out models the parser-inserted case.

default: true
example: parserInserted=false
nonce string

The element's nonce attribute, i.e. the request's cryptographic nonce metadata. Compared byte-for-byte with each nonce-source's base64-value (§6.7.2.3) — case-sensitive, no decoding. Consulted only by the script and style directives' pre-request checks (§6.7.1.1, §6.1.13.1, §6.1.14.1); ignored with a warning for any other effective directive. The base64-value grammar admits '+', which a query string reads as a space, so percent-encode it as %2B here and in 'policy'.

allowed: ≤ 256
example: nonce=r4nd0mB4se64Value1234567
integrity string

The element's integrity attribute. Per §6.7.2.4 every hash in the metadata must be listed as a hash-source in the directive for the request to be allowed; the comparison is algorithm plus base64 string equality, with base64url and base64 treated as equivalent, so no hashing happens. Consulted only by the script element directives; ignored with a warning otherwise.

allowed: ≤ 512
example: integrity=sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
redirectCount int

The request's redirect count. When it is not 0, §6.7.2.8 skips path matching entirely — a deliberate compromise against cross-origin path leaks (§7.6).

default: 0
allowed: 0 – 20
example: redirectCount=1
disposition enum

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

default: enforce
allowed: enforce | report
example: disposition=report
source enum

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

default: header
allowed: header | meta
example: source=meta
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=decision,explanation
exclude list

Return all fields except these (comma-separated).

example: exclude=ambiguities
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 10
decision string

allowed, blocked or ambiguous. Blocked when any enforced policy blocks (§8.1); report-only policies never contribute. ambiguous fires only for the enumerated draft contradictions in ambiguities that actually change this answer.

example: blocked

explanation string

One sentence naming what decided and why — the answer to read first.

example: 'strict-dynamic' is present in 'script-src', so the parser-inserted script request is blocked before the host allowlist is ever consulted.

effectiveDirective string

The effective directive name for this context (§6.8.1), or the non-fetch check name for context=base-uri, form-action or frame-ancestors.

example: script-src-elem

fallbackChain string[]

The ordered §6.8.3 list walked, most relevant first, including the effective directive itself. A single-item list for the three non-fetch checks — they have no default-src fallback.

example: ["script-src-elem","script-src","default-src"]

governed boolean

Whether any enforced policy declares a directive in the chain. False means the load is simply not restricted by what you pasted.

example: true

decidedBy object nullable

{ policyIndex, directive, sourceList, step, specSection, specUrl } for the first enforced policy that blocks, or — when allowed — the last enforced policy that had to be satisfied. Null when nothing governs the load. step is one of nonce-match, integrity-match, strict-dynamic-parser-inserted, strict-dynamic-non-parser-inserted, source-list-match, source-list-no-match, empty-source-list, none-keyword, not-governed, ignored-in-meta or ignored-in-report-only.

example: {"policyIndex":0,"directive":"script-src","sourceList":["'nonce-r4nd0mB4se64Value1234567'","'strict-dynamic'"],"step":"strict-dynamic-parser-inserted","specSection":"6.7.1.1","specUrl":"https://www.w3.org/TR/CSP3/#script-pre-request"}

matchedExpression string nullable

The source expression that matched, verbatim as written in the policy, or null when nothing matched or matching never ran.

example: null

wouldReport boolean

Whether at least one policy — enforced or report-only — would generate a violation report.

example: true

policies object[]

Per policy: { index, disposition, decision, chainWalk, expressionResults, reason }. chainWalk is one entry per name in fallbackChain: { name, present, executed, note } — at most one entry can be executed, because §6.8.4 lets only the first declared name in the chain execute and every other directive defers. expressionResults is one entry per source expression of the executing directive, and is empty whenever URL matching never ran: { raw, matches, failedAt, detail } with failedAt one of scheme-part, host-part, port-part, path-part, null-host, not-a-domain, self-mismatch, keyword-not-a-url-match, not-a-url-source-expression, none-with-siblings, or null when it matched.

example: [{"index":0,"disposition":"enforce","decision":"blocked","chainWalk":[{"name":"script-src-elem","present":false,"executed":false,"note":"Not declared, so it defers to the next name in the chain."},{"name":"script-src","present":true,"executed":true,"note":null},{"name":"default-src","present":true,"executed":false,"note":"Declared, but 'script-src' is more relevant and executes instead."}],"expressionResults":[],"reason":"strict-dynamic-parser-inserted"}]

ambiguities object[]

Same shape and closed vocabulary as /evaluate, present here only when a contradiction in the pinned draft bears on this exact decision.

example: []

Documented examples

Build-generated requests and complete responses
5
Why strict-dynamic blocked my CDN script
GET /api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com
{
  "data": {
    "decision": "blocked",
    "explanation": "'strict-dynamic' is present in 'script-src', so the parser-inserted script request is blocked before the host allowlist is ever consulted.",
    "effectiveDirective": "script-src-elem",
    "fallbackChain": [
      "script-src-elem",
      "script-src",
      "default-src"
    ],
    "governed": true,
    "decidedBy": {
      "policyIndex": 0,
      "directive": "script-src",
      "sourceList": [
        "'nonce-r4nd0mB4se64Value1234567'",
        "'strict-dynamic'"
      ],
      "step": "strict-dynamic-parser-inserted",
      "specSection": "6.7.1.1",
      "specUrl": "https://www.w3.org/TR/CSP3/#script-pre-request"
    },
    "matchedExpression": null,
    "wouldReport": true,
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "decision": "blocked",
        "chainWalk": [
          {
            "name": "script-src-elem",
            "present": false,
            "executed": false,
            "note": "Not declared, so it defers to the next name in the chain."
          },
          {
            "name": "script-src",
            "present": true,
            "executed": true,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
The same script created by createElement is allowed
GET /api/csp/check?policy=script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'&resource=https%3A%2F%2Fcdn.example.com%2Fapp.js&self=https%3A%2F%2Fexample.com&parserInserted=false
{
  "data": {
    "decision": "allowed",
    "explanation": "'strict-dynamic' is present in 'script-src', and the script element was not parser-inserted, so it is allowed regardless of the host allowlist.",
    "effectiveDirective": "script-src-elem",
    "fallbackChain": [
      "script-src-elem",
      "script-src",
      "default-src"
    ],
    "governed": true,
    "decidedBy": {
      "policyIndex": 0,
      "directive": "script-src",
      "sourceList": [
        "'nonce-r4nd0mB4se64Value1234567'",
        "'strict-dynamic'"
      ],
      "step": "strict-dynamic-non-parser-inserted",
      "specSection": "6.7.1.1",
      "specUrl": "https://www.w3.org/TR/CSP3/#script-pre-request"
    },
    "matchedExpression": null,
    "wouldReport": false,
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "decision": "allowed",
        "chainWalk": [
          {
            "name": "script-src-elem",
            "present": false,
            "executed": false,
            "note": "Not declared, so it defers to the next name in the chain."
          },
          {
            "name": "script-src",
            "present": true,
            "executed": true,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
frame-src falls back to child-src
GET /api/csp/check?policy=default-src%20'self'%3B%20child-src%20https%3A%2F%2Fembed.example.com&resource=https%3A%2F%2Fembed.example.com%2Fwidget&self=https%3A%2F%2Fexample.com&context=iframe
{
  "data": {
    "decision": "allowed",
    "explanation": "The URL matches https://embed.example.com in 'child-src'.",
    "effectiveDirective": "frame-src",
    "fallbackChain": [
      "frame-src",
      "child-src",
      "default-src"
    ],
    "governed": true,
    "decidedBy": {
      "policyIndex": 0,
      "directive": "child-src",
      "sourceList": [
        "https://embed.example.com"
      ],
      "step": "source-list-match",
      "specSection": "6.7.2.7",
      "specUrl": "https://www.w3.org/TR/CSP3/#match-url-to-source-list"
    },
    "matchedExpression": "https://embed.example.com",
    "wouldReport": false,
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "decision": "allowed",
        "chainWalk": [
          {
            "name": "frame-src",
            "present": false,
            "executed": false,
            "note": "Not declared, so it defers to the next name in the chain."
          },
          {
            "name": "child-src",
            "present": true,
            "executed": true,
            "note": null"generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
default-src 'none' does not stop a form post
GET /api/csp/check?policy=default-src%20'none'&resource=https%3A%2F%2Fevil.example%2Fsteal&self=https%3A%2F%2Fexample.com&context=form-action
{
  "data": {
    "decision": "allowed",
    "explanation": "No directive in the « form-action » fallback chain is declared by an enforced policy, so nothing in this policy restricts the load.",
    "effectiveDirective": "form-action",
    "fallbackChain": [
      "form-action"
    ],
    "governed": false,
    "decidedBy": null,
    "matchedExpression": null,
    "wouldReport": false,
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "decision": "allowed",
        "chainWalk": [
          {
            "name": "form-action",
            "present": false,
            "executed": false,
            "note": "Not declared, so this policy does not restrict this check at all."
          }
        ],
        "expressionResults": [],
        "reason": "not-governed"
      }
    ],
    "ambiguities": []
  },
  "meta": {
    "endpoint": "csp",
    "route": "/check",
    "params": {
      "policy": "default-src 'none'",
      "resource": "https://evil.example/steal",
      "self": "https://example.com",
      "context": "form-action",
      "parserInserted": true,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
A path is ignored after a redirect
GET /api/csp/check?policy=img-src%20example.org%2Fpath&resource=https%3A%2F%2Fexample.org%2Fnot-path&self=https%3A%2F%2Fexample.com&context=image&redirectCount=1
{
  "data": {
    "decision": "allowed",
    "explanation": "The URL matches example.org/path in 'img-src'.",
    "effectiveDirective": "img-src",
    "fallbackChain": [
      "img-src",
      "default-src"
    ],
    "governed": true,
    "decidedBy": {
      "policyIndex": 0,
      "directive": "img-src",
      "sourceList": [
        "example.org/path"
      ],
      "step": "source-list-match",
      "specSection": "6.7.2.7",
      "specUrl": "https://www.w3.org/TR/CSP3/#match-url-to-source-list"
    },
    "matchedExpression": "example.org/path",
    "wouldReport": false,
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "decision": "allowed",
        "chainWalk": [
          {
            "name": "img-src",
            "present": true,
            "executed": true,
            "note": null
          },
          {
            "name": "default-src",
            "present": false,
            "executed": false,
            "note": "Not declared, so it defers to the next name in the chain."
          }
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

GET /api/csp/parse

Runs the CSP3 §2.2.1 parse algorithm over the policy you paste: directive names lowercased, duplicate directives dropped the way a user agent drops them, every source expression classified against the §2.3.1 grammar. Nothing is fetched and no verdict about a URL is reached — use /check for that.

Live requestRuns against the public API
No key required
GET/api/csp/parse?policy=default-src+%27self%27%3B+script-src+%27nonce-r4nd0mB4se64Value1234567%27+%27strict-dynamic%27

Request parameters

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/csp/parse?policy=default-src%20'self'%3B%20script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'"
const res = await fetch("https://randomapi.dev/api/csp/parse?policy=default-src%20'self'%3B%20script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/csp/parse?policy=default-src%20'self'%3B%20script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/csp/parse?policy=default-src%20'self'%3B%20script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
policy string required

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

allowed: 1 – 4096
example: policy=default-src 'self'; script-src 'nonce-r4nd0mB4se64Value1234567' 'strict-dynamic'
source enum

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

default: header
allowed: header | meta
example: source=meta
disposition enum

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

default: enforce
allowed: enforce | report
example: disposition=report
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=policyCount,normalized
exclude list

Return all fields except these (comma-separated).

example: exclude=policies
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 5
policyCount integer

Number of serialized policies found in the value; a comma starts a new one (§2.2.2). A policy whose directive set is empty is reported here so you can see you wrote it, even though §2.2.2 drops such a policy when it builds the CSP list — an empty policy restricts nothing.

example: 1

normalized string

Conservative re-serialization: directive names ASCII-lowercased, runs of ASCII whitespace collapsed to one space, ignored tokens and duplicate directives removed, directives joined with "; " and policies with ", ". Source-expression text is never rewritten — nonces are compared byte-for-byte, so rewriting them would be a lie.

example: default-src 'self'; script-src 'nonce-r4nd0mB4se64Value1234567' 'strict-dynamic'

unknownDirectives string[]

Lowercased directive names this API's directive table does not know, de-duplicated and sorted. A user agent keeps them in the policy but has no algorithm for them, so they are inert.

example: ["script-scr"]

duplicateDirectives string[]

Names that appeared more than once; every occurrence after the first is ignored (§2.2.1). Sorted and de-duplicated.

example: ["script-src"]

policies object[]

One entry per policy: { index, disposition, source, directives, ignoredTokens }. Each directives entry is { name, rawName, value, type, status, fallbackChain, ignored, ignoredReason, specSection, specUrl, sources }; every field but the first three is null for a directive outside the table. sources is present only for source-list-valued directives and each entry is { raw, kind, valid, keyword, scheme, host, port, path, hashAlgorithm, base64Value, note } where kind is one of scheme-source, host-source, keyword-source, nonce-source, hash-source, none or invalid. ignoredReason is duplicate-directive, ignored-in-meta, ignored-in-report-only or null. ignoredTokens entries are { raw, reason } with reason empty-token or non-ascii-token — §2.2.1 skips both.

example: [{"index":0,"disposition":"enforce","source":"header","directives":[{"name":"script-src","rawName":"script-src","value":["'nonce-abc'","'strict-dynamic'"],"type":"fetch","status":"csp3","fallbackChain":["script-src"],"ignored":false,"ignoredReason":null,"specSection":"6.1.10","specUrl":"https://www.w3.org/TR/CSP3/#directive-script-src","sources":[{"raw":"'nonce-abc'","kind":"nonce-source","valid":true,"keyword":null,"scheme":null,"host":null,"port":null,"path":null,"hashAlgorithm":null,"base64Value":"abc","note":"A nonce shorter than 22 base64 characters carries fewer than the 128 bits CSP3 §7.1 recommends."}]}],"ignoredTokens":[]}]

Documented examples

Build-generated requests and complete responses
4
Nonce plus strict-dynamic
GET /api/csp/parse?policy=default-src%20'self'%3B%20script-src%20'nonce-r4nd0mB4se64Value1234567'%20'strict-dynamic'
{
  "data": {
    "policyCount": 1,
    "normalized": "default-src 'self'; script-src 'nonce-r4nd0mB4se64Value1234567' 'strict-dynamic'",
    "unknownDirectives": [],
    "duplicateDirectives": [],
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "source": "header",
        "directives": [
          {
            "name": "default-src",
            "rawName": "default-src",
            "value": [
              "'self'"
            ],
            "type": "fetch",
            "status": "csp3",
            "fallbackChain": [
              "default-src"
            ],
            "ignored": false,
            "ignoredReason": null,
            "specSection": "6.1.3",
            "specUrl": "https://www.w3.org/TR/CSP3/#directive-default-src",
            "sources": [
              {
                "raw": "'self'",
                "kind": "keyword-source",
                "valid": true,
                "keyword": "'self'",
                "scheme": null,
                "host": null,
                "port": null,
                "path": null,
                "hashAlgorithm": null,
                "base64Value": null,
                "note": null"generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Duplicate and mistyped directives
GET /api/csp/parse?policy=script-src%20'self'%3B%20script-scr%20https%3A%2F%2Fcdn.example.com%3B%20script-src%20'none'
{
  "data": {
    "policyCount": 1,
    "normalized": "script-src 'self'; script-scr https://cdn.example.com",
    "unknownDirectives": [
      "script-scr"
    ],
    "duplicateDirectives": [
      "script-src"
    ],
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "source": "header",
        "directives": [
          {
            "name": "script-src",
            "rawName": "script-src",
            "value": [
              "'self'"
            ],
            "type": "fetch",
            "status": "csp3",
            "fallbackChain": [
              "script-src"
            ],
            "ignored": false,
            "ignoredReason": null,
            "specSection": "6.1.10",
            "specUrl": "https://www.w3.org/TR/CSP3/#directive-script-src",
            "sources": [
              {
                "raw": "'self'",
                "kind": "keyword-source",
                "valid": true,
                "keyword": "'self'",
                "scheme": null,
                "host": null,
                "port": null,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
A comma makes it two policies
GET /api/csp/parse?policy=default-src%20'self'%2Cscript-src%20https%3A%2F%2Fcdn.example.com
{
  "data": {
    "policyCount": 2,
    "normalized": "default-src 'self', script-src https://cdn.example.com",
    "unknownDirectives": [],
    "duplicateDirectives": [],
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "source": "header",
        "directives": [
          {
            "name": "default-src",
            "rawName": "default-src",
            "value": [
              "'self'"
            ],
            "type": "fetch",
            "status": "csp3",
            "fallbackChain": [
              "default-src"
            ],
            "ignored": false,
            "ignoredReason": null,
            "specSection": "6.1.3",
            "specUrl": "https://www.w3.org/TR/CSP3/#directive-default-src",
            "sources": [
              {
                "raw": "'self'",
                "kind": "keyword-source",
                "valid": true,
                "keyword": "'self'",
                "scheme": null,
                "host": null,
                "port": null,
                "path": null,
                "hashAlgorithm": null,
                "base64Value": null,
                "note": null
    …
    ]
  }
}
meta delivery drops frame-ancestors and sandbox
GET /api/csp/parse?policy=frame-ancestors%20'none'%3B%20sandbox%3B%20script-src%20'self'&source=meta
{
  "data": {
    "policyCount": 1,
    "normalized": "frame-ancestors 'none'; sandbox; script-src 'self'",
    "unknownDirectives": [],
    "duplicateDirectives": [],
    "policies": [
      {
        "index": 0,
        "disposition": "enforce",
        "source": "meta",
        "directives": [
          {
            "name": "frame-ancestors",
            "rawName": "frame-ancestors",
            "value": [
              "'none'"
            ],
            "type": "navigation",
            "status": "csp3",
            "fallbackChain": [
              "frame-ancestors"
            ],
            "ignored": true,
            "ignoredReason": "ignored-in-meta",
            "specSection": "6.4.2",
            "specUrl": "https://www.w3.org/TR/CSP3/#directive-frame-ancestors",
            "sources": [
              {
                "raw": "'none'",
                "kind": "none",
                "valid": true,
                "keyword": "'none'",
                "scheme": null,
                "host": null,
                "port": null,
                "path": null,
                "hashAlgorithm": null,
                "base64Value": null,
                "note": "'none' matches nothing, and it only makes the whole directive match nothing while it is the single expression in the list (CSP3 §6.7.2.7)."
    …
    ]
  }
}

GET /api/csp/evaluate

Returns ranked findings and a coverage table: for each protection surface, which directive governs it after the fallback chain, and whether inline content is allowed. Every finding cites the CSP3 clause it rests on. There is deliberately no grade and no score.

Live requestRuns against the public API
No key required
GET/api/csp/evaluate?policy=default-src+%27self%27

Request parameters

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/csp/evaluate?policy=default-src%20'self'"
const res = await fetch("https://randomapi.dev/api/csp/evaluate?policy=default-src%20'self'");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/csp/evaluate?policy=default-src%20'self'").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/csp/evaluate?policy=default-src%20'self'"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
policy string required

The Content-Security-Policy header value, verbatim. Directives are separated by ';' and a comma starts a second policy — a comma-separated list is parsed as a list and every policy in it is evaluated, because enforcing several policies can only further restrict a page (CSP3 §8.1). At most 4096 characters, 8 policies, 32 directives per policy, 64 source expressions per directive and 256 source expressions in total; anything larger is rejected, never truncated.

allowed: 1 – 4096
example: policy=default-src 'self'; script-src 'nonce-r4nd0mB4se64Value1234567' 'strict-dynamic'
source enum

How the policy is delivered. 'meta' models an HTML <meta http-equiv> policy, in which the report-uri, frame-ancestors and sandbox directives are not supported and are therefore ignored (CSP3 §3.3).

default: header
allowed: header | meta
example: source=meta
disposition enum

'enforce' models Content-Security-Policy; 'report' models Content-Security-Policy-Report-Only, which never blocks anything — it only reports. The sandbox directive is additionally ignored in a report-only policy (CSP3 §6.3.2).

default: enforce
allowed: enforce | report
example: disposition=report
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=policyCount,findings
exclude list

Return all fields except these (comma-separated).

example: exclude=ambiguities
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 5
policyCount integer

Policies evaluated.

example: 1

findings object[]

{ id, severity, policyIndex, directive, expression, occurrences, title, detail, specSection, specUrl }. severity is high, medium, low or info — this API's own documented ranking of how much of the policy's protection the condition removes. It is not a CVSS score, not a vulnerability rating, and there is no aggregate grade. directive and expression are null for whole-policy findings. There is one finding per condition per directive: expression names the first offending expression and occurrences counts how many expressions in that directive share the condition, so sixty subdomain wildcards are one finding rather than sixty. Sorted by severity, then policy, then id.

example: [{"id":"object-src-not-restricted","severity":"high","policyIndex":0,"directive":null,"expression":null,"occurrences":1,"title":"object and embed loads are unrestricted","detail":"Neither 'object-src' nor 'default-src' is present, so nothing in the « object-src, default-src » fallback chain governs object and embed requests. 'object-src' is the one fetch directive worth setting to 'none' on almost every page.","specSection":"6.1.9","specUrl":"https://www.w3.org/TR/CSP3/#directive-object-src"}]

findingCounts object

{ high, medium, low, info } — counts only. There is no total, no score and no grade.

example: {"high":1,"medium":2,"low":0,"info":1}

coverage object[]

Fifteen fixed rows: the twelve effective fetch-directive names §6.8.3 defines a fallback list for, plus base-uri, form-action and frame-ancestors. Each row is { effectiveDirective, fallbackChain, restricted, perPolicy }; perPolicy entries are { policyIndex, governedBy, sourceList, allowsAllInline }. governedBy is the first name in the chain the policy actually declares (§6.8.4), and both it and sourceList are null when the policy does not govern the surface at all. allowsAllInline is the §6.7.3.2 answer for the four inline surfaces, and null for the other eleven rows and for an ungoverned surface. restricted is true when at least one enforced policy governs the surface.

example: [{"effectiveDirective":"script-src-elem","fallbackChain":["script-src-elem","script-src","default-src"],"restricted":true,"perPolicy":[{"policyIndex":0,"governedBy":"script-src","sourceList":["'nonce-r4nd0mB4se64Value1234567'","'strict-dynamic'"],"allowsAllInline":false}]}]

ambiguities object[]

Places where the pinned CSP3 draft contradicts itself that this policy actually triggers: { id, detail, normativeReading, informativeReading, specSections }. The vocabulary is closed at three ids — ip-literal-host-vs-host-part-match, explicit-insecure-default-port-vs-secure-upgrade and unsafe-allow-redirects-undefined — and empty for most policies. This API always follows the normative algorithm and says so.

example: []

Documented examples

Build-generated requests and complete responses
5
A minimal policy still leaves base-uri and form-action open
GET /api/csp/evaluate?policy=default-src%20'self'
{
  "data": {
    "policyCount": 1,
    "findings": [
      {
        "id": "base-uri-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "a base element may retarget every relative URL",
        "detail": "No 'base-uri' directive is present, and 'default-src' is not a fallback for it — the §6.8.3 fallback lists never mention it — so injected markup can set a base URL that retargets every relative URL on the page.",
        "specSection": "6.3.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-base-uri"
      },
      {
        "id": "form-action-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "form submissions may target any origin",
        "detail": "No 'form-action' directive is present, and 'default-src' is not a fallback for it, so a form can post to any origin even under 'default-src' 'none'.",
        "specSection": "6.4.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-form-action"
      },
      {
        "id": "frame-ancestors-not-restricted",
        "severity": "low",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "any page may embed this document in a frame",
        "detail": "No 'frame-ancestors' directive is present. The pinned draft states outright that a policy declaring 'default-src' 'none' still allows the resource to be embedded by anyone.",
        "specSection": "6.4.2",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-frame-ancestors"
      },
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
No default-src leaves object-src ungoverned
GET /api/csp/evaluate?policy=script-src%20'self'%3B%20style-src%20'self'
{
  "data": {
    "policyCount": 1,
    "findings": [
      {
        "id": "object-src-not-restricted",
        "severity": "high",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "object and embed loads are unrestricted",
        "detail": "Neither 'object-src' nor 'default-src' is present, so nothing in the « object-src, default-src » fallback chain governs object and embed requests. 'object-src' is the one fetch directive worth setting to 'none' on almost every page.",
        "specSection": "6.1.9",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-object-src"
      },
      {
        "id": "base-uri-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "a base element may retarget every relative URL",
        "detail": "No 'base-uri' directive is present, and 'default-src' is not a fallback for it — the §6.8.3 fallback lists never mention it — so injected markup can set a base URL that retargets every relative URL on the page.",
        "specSection": "6.3.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-base-uri"
      },
      {
        "id": "form-action-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "form submissions may target any origin",
        "detail": "No 'form-action' directive is present, and 'default-src' is not a fallback for it, so a form can post to any origin even under 'default-src' 'none'.",
        "specSection": "6.4.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-form-action"
      },
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
A nonce makes unsafe-inline inert
GET /api/csp/evaluate?policy=script-src%20'unsafe-inline'%20'nonce-r4nd0mB4se64Value1234567'
{
  "data": {
    "policyCount": 1,
    "findings": [
      {
        "id": "object-src-not-restricted",
        "severity": "high",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "object and embed loads are unrestricted",
        "detail": "Neither 'object-src' nor 'default-src' is present, so nothing in the « object-src, default-src » fallback chain governs object and embed requests. 'object-src' is the one fetch directive worth setting to 'none' on almost every page.",
        "specSection": "6.1.9",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-object-src"
      },
      {
        "id": "base-uri-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "a base element may retarget every relative URL",
        "detail": "No 'base-uri' directive is present, and 'default-src' is not a fallback for it — the §6.8.3 fallback lists never mention it — so injected markup can set a base URL that retargets every relative URL on the page.",
        "specSection": "6.3.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-base-uri"
      },
      {
        "id": "form-action-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "form submissions may target any origin",
        "detail": "No 'form-action' directive is present, and 'default-src' is not a fallback for it, so a form can post to any origin even under 'default-src' 'none'.",
        "specSection": "6.4.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-form-action"
      },
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
A short nonce misses the 128-bit recommendation
GET /api/csp/evaluate?policy=script-src%20'nonce-abcd'
{
  "data": {
    "policyCount": 1,
    "findings": [
      {
        "id": "object-src-not-restricted",
        "severity": "high",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "object and embed loads are unrestricted",
        "detail": "Neither 'object-src' nor 'default-src' is present, so nothing in the « object-src, default-src » fallback chain governs object and embed requests. 'object-src' is the one fetch directive worth setting to 'none' on almost every page.",
        "specSection": "6.1.9",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-object-src"
      },
      {
        "id": "base-uri-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "a base element may retarget every relative URL",
        "detail": "No 'base-uri' directive is present, and 'default-src' is not a fallback for it — the §6.8.3 fallback lists never mention it — so injected markup can set a base URL that retargets every relative URL on the page.",
        "specSection": "6.3.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-base-uri"
      },
      {
        "id": "form-action-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "form submissions may target any origin",
        "detail": "No 'form-action' directive is present, and 'default-src' is not a fallback for it, so a form can post to any origin even under 'default-src' 'none'.",
        "specSection": "6.4.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-form-action"
      },
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Report-only enforces nothing
GET /api/csp/evaluate?policy=default-src%20'none'&disposition=report
{
  "data": {
    "policyCount": 1,
    "findings": [
      {
        "id": "base-uri-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "a base element may retarget every relative URL",
        "detail": "No 'base-uri' directive is present, and 'default-src' is not a fallback for it — the §6.8.3 fallback lists never mention it — so injected markup can set a base URL that retargets every relative URL on the page.",
        "specSection": "6.3.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-base-uri"
      },
      {
        "id": "form-action-not-restricted",
        "severity": "medium",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "form submissions may target any origin",
        "detail": "No 'form-action' directive is present, and 'default-src' is not a fallback for it, so a form can post to any origin even under 'default-src' 'none'.",
        "specSection": "6.4.1",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-form-action"
      },
      {
        "id": "frame-ancestors-not-restricted",
        "severity": "low",
        "policyIndex": 0,
        "directive": null,
        "expression": null,
        "occurrences": 1,
        "title": "any page may embed this document in a frame",
        "detail": "No 'frame-ancestors' directive is present. The pinned draft states outright that a policy declaring 'default-src' 'none' still allows the resource to be embedded by anyone.",
        "specSection": "6.4.2",
        "specUrl": "https://www.w3.org/TR/CSP3/#directive-frame-ancestors"
      },
    …
    ]
  }
}

GET /api/csp/directives

All 30 directive names an author might write, each classified by a citable status: the 23 defined by the pinned CSP Level 3 draft, the four defined by other W3C specifications, the CSP2-only row and the two names removed from an earlier draft.

Live requestRuns against the public API
No key required
GET/api/csp/directives?type=fetch

Request parameters

Case-insensitive substring match against the directive name and the 'governs' sentence.

The CSP3 §6.1–§6.5 grouping. 'unclassified' is every row the pinned draft does not group: the four directives defined by other W3C specifications, the CSP2-only row and the two removed-draft rows.

Where the directive is defined and whether it still is: csp3, csp3-deprecated, other-spec, other-spec-obsolete, csp2-only or removed-draft.

true selects rows whose fallbackChain has more than one entry; false selects the rows §6.8.3 gives no fallback list.

true selects the three directives a <meta>-delivered policy does not support (§3.3): report-uri, frame-ancestors and sandbox.

Advanced response options6 options

Limit the number of returned records (1–100). Defaults to all matches.

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Response format: json envelope, ndjson (one record per line) or csv.

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/csp/directives?type=fetch"
const res = await fetch("https://randomapi.dev/api/csp/directives?type=fetch");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/csp/directives?type=fetch").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/csp/directives?type=fetch"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 5
search string

Case-insensitive substring match against the directive name and the 'governs' sentence.

allowed: 1 – 64
example: search=worker
type enum

The CSP3 §6.1–§6.5 grouping. 'unclassified' is every row the pinned draft does not group: the four directives defined by other W3C specifications, the CSP2-only row and the two removed-draft rows.

allowed: fetch | other | document | navigation | reporting | unclassified
example: type=fetch
status enum

Where the directive is defined and whether it still is: csp3, csp3-deprecated, other-spec, other-spec-obsolete, csp2-only or removed-draft.

allowed: csp3 | csp3-deprecated | other-spec | other-spec-obsolete | csp2-only | removed-draft
example: status=removed-draft
hasFallback boolean

true selects rows whose fallbackChain has more than one entry; false selects the rows §6.8.3 gives no fallback list.

example: hasFallback=true
ignoredInMeta boolean

true selects the three directives a <meta>-delivered policy does not support (§3.3): report-uri, frame-ancestors and sandbox.

example: ignoredInMeta=true
Universal parameters Shared response and formatting options 6
count int

Limit the number of returned records (1–100). Defaults to all matches.

default: all matches
allowed: 1 – 100
example: count=3
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=name,type
exclude list

Return all fields except these (comma-separated).

example: exclude=specUrl
format enum

Response format: json envelope, ndjson (one record per line) or csv.

default: json
allowed: json | ndjson | csv
example: format=csv
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 17
name string

Lowercased directive name.

example: frame-src

type string

The CSP3 §6.1–§6.5 grouping: fetch, other, document, navigation or reporting. 'unclassified' is every row the pinned draft does not group — the four directives defined by other W3C specifications, the CSP2-only row and the two removed-draft rows.

example: fetch

status string

csp3 (defined in the pinned draft), csp3-deprecated, other-spec (defined by another W3C specification), other-spec-obsolete, csp2-only or removed-draft.

example: csp3

statusNote string nullable

One sentence of provenance for a non-csp3 status; null for a plain csp3 row. Our own wording, never copied prose.

example: null

governs string

One original sentence describing what the directive controls, written from the specification's normative prose rather than copied from it.

example: Requests that populate a child navigable, such as an iframe or frame navigation.

valueGrammar string

The ABNF production the directive's value follows.

example: serialized-source-list

fallbackChain string[]

The ordered §6.8.3 fallback list, most relevant first, including the directive itself. Just [name] for the directives §6.8.3 does not cover — which includes script-src, style-src, child-src and every non-fetch directive.

example: ["frame-src","child-src","default-src"]

fallbackParent string nullable

The next name after this one in fallbackChain, or null.

example: child-src

destinations string[]

Fetch request destinations for which §6.8.1 returns exactly this name. Empty for every directive reached only as a fallback (child-src, script-src, style-src) and for the non-fetch directives.

example: ["frame","iframe"]

ignoredInMeta boolean

Whether a <meta>-delivered policy ignores this directive (§3.3: report-uri, frame-ancestors and sandbox).

example: false

ignoredInReportOnly boolean

Whether a report-only policy ignores it (§6.3.2: sandbox only).

example: false

consultsNonce boolean

Whether this directive's own pre-request check consults the request's cryptographic nonce metadata (§6.7.2.3) — directly for the script and style directives, and for default-src through the check it delegates to (§6.1.3.1). False for the two attribute directives, which have an inline check and no pre-request check.

example: false

consultsIntegrity boolean

Whether it consults the request's integrity metadata (§6.7.2.4). The script element directives only, plus default-src by delegation.

example: false

honorsStrictDynamic boolean

Whether 'strict-dynamic' changes the URL matching this directive performs (§6.7.1.1): true for script-src, script-src-elem and default-src, false for every other directive — in img-src the keyword is inert. /evaluate narrows this per policy, because default-src only reaches the script check when no script directive is declared.

example: false

ianaRegistered boolean

Whether the name appears in the pinned IANA Content Security Policy Directives registry snapshot (last updated 2023-02-03). The registry still holds only the sixteen CSP Level 2 names, so most CSP3 additions are false.

example: true

specSection string

Section number in the document that defines it.

example: 6.1.5

specUrl string

Deep link to that section.

example: https://www.w3.org/TR/CSP3/#directive-frame-src

Documented examples

Build-generated requests and complete responses
4
Every fetch directive
GET /api/csp/directives?type=fetch
{
  "data": [
    {
      "name": "child-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Requests that create a child navigable or a worker. It is reached only as the fallback for frame-src and worker-src, and it hands the decision to whichever of those two the request actually belongs to.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "child-src"
      ],
      "fallbackParent": null,
      "destinations": [],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": false,
      "consultsIntegrity": false,
      "honorsStrictDynamic": false,
      "ianaRegistered": true,
      "specSection": "6.1.1",
      "specUrl": "https://www.w3.org/TR/CSP3/#directive-child-src"
    },
    {
      "name": "connect-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Script-initiated network requests: fetch(), XMLHttpRequest, WebSocket, EventSource and sendBeacon, plus any Fetch destination the specification does not route to a more specific directive.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "connect-src",
        "default-src"
      ],
      "fallbackParent": "default-src",
      "destinations": [
        "empty",
        "json",
        "text",
        "webidentity""generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Only the directives with a fallback chain
GET /api/csp/directives?hasFallback=true
{
  "data": [
    {
      "name": "connect-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Script-initiated network requests: fetch(), XMLHttpRequest, WebSocket, EventSource and sendBeacon, plus any Fetch destination the specification does not route to a more specific directive.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "connect-src",
        "default-src"
      ],
      "fallbackParent": "default-src",
      "destinations": [
        "empty",
        "json",
        "text",
        "webidentity"
      ],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": false,
      "consultsIntegrity": false,
      "honorsStrictDynamic": false,
      "ianaRegistered": true,
      "specSection": "6.1.2",
      "specUrl": "https://www.w3.org/TR/CSP3/#directive-connect-src"
    },
    {
      "name": "font-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Font files fetched for an @font-face rule.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "font-src",
        "default-src"
      ],
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Names removed from an earlier draft
GET /api/csp/directives?status=removed-draft
{
  "data": [
    {
      "name": "prefetch-src",
      "type": "unclassified",
      "status": "removed-draft",
      "statusNote": "Present in the 29 June 2021 CSP Level 3 Working Draft and removed before the pinned 29 July 2026 revision, so nothing in the current draft gives it behaviour.",
      "governs": "Formerly restricted the URLs that prefetch and prerender requests were allowed to target.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "prefetch-src"
      ],
      "fallbackParent": null,
      "destinations": [],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": false,
      "consultsIntegrity": false,
      "honorsStrictDynamic": false,
      "ianaRegistered": false,
      "specSection": "6.1.10",
      "specUrl": "https://www.w3.org/TR/2021/WD-CSP3-20210629/#directive-prefetch-src"
    },
    {
      "name": "navigate-to",
      "type": "unclassified",
      "status": "removed-draft",
      "statusNote": "Present in the 29 June 2021 CSP Level 3 Working Draft and removed before the pinned 29 July 2026 revision, so nothing in the current draft gives it behaviour.",
      "governs": "Formerly restricted the URLs this document could navigate to by any means, deferring form submissions to form-action when that was also present.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "navigate-to"
      ],
      "fallbackParent": null,
      "destinations": [],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": false,
      "consultsIntegrity": false,
      "honorsStrictDynamic": false,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Search for the worker directives
GET /api/csp/directives?search=worker
{
  "data": [
    {
      "name": "child-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Requests that create a child navigable or a worker. It is reached only as the fallback for frame-src and worker-src, and it hands the decision to whichever of those two the request actually belongs to.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "child-src"
      ],
      "fallbackParent": null,
      "destinations": [],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": false,
      "consultsIntegrity": false,
      "honorsStrictDynamic": false,
      "ianaRegistered": true,
      "specSection": "6.1.1",
      "specUrl": "https://www.w3.org/TR/CSP3/#directive-child-src"
    },
    {
      "name": "script-src",
      "type": "fetch",
      "status": "csp3",
      "statusNote": null,
      "governs": "Every script-like request and inline script surface, plus the eval() and WebAssembly compilation gates. It is the fallback for the four granular script directives and, through child-src, for workers.",
      "valueGrammar": "serialized-source-list",
      "fallbackChain": [
        "script-src"
      ],
      "fallbackParent": null,
      "destinations": [],
      "ignoredInMeta": false,
      "ignoredInReportOnly": false,
      "consultsNonce": true,
      "consultsIntegrity": true,
      "honorsStrictDynamic": true,
    …
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

GET /api/csp/lookup

Returns one directive row. The name is matched case-insensitively after ASCII-lowercasing, exactly as §2.2.1 lowercases directive names; an unknown name is an explicit 404 with a suggestion, never a substitute row.

Live requestRuns against the public API
No key required
GET/api/csp/lookup?name=frame-src

Request parameters

Directive name, matched case-insensitively after ASCII-lowercasing. Must be an HTTP token.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/csp/lookup?name=frame-src"
const res = await fetch("https://randomapi.dev/api/csp/lookup?name=frame-src");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/csp/lookup?name=frame-src").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/csp/lookup?name=frame-src"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 1
name string required

Directive name, matched case-insensitively after ASCII-lowercasing. Must be an HTTP token.

allowed: 1 – 64
example: name=frame-src
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=name,type
exclude list

Return all fields except these (comma-separated).

example: exclude=specUrl
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 17
name string

Lowercased directive name.

example: frame-src

type string

The CSP3 §6.1–§6.5 grouping: fetch, other, document, navigation or reporting. 'unclassified' is every row the pinned draft does not group — the four directives defined by other W3C specifications, the CSP2-only row and the two removed-draft rows.

example: fetch

status string

csp3 (defined in the pinned draft), csp3-deprecated, other-spec (defined by another W3C specification), other-spec-obsolete, csp2-only or removed-draft.

example: csp3

statusNote string nullable

One sentence of provenance for a non-csp3 status; null for a plain csp3 row. Our own wording, never copied prose.

example: null

governs string

One original sentence describing what the directive controls, written from the specification's normative prose rather than copied from it.

example: Requests that populate a child navigable, such as an iframe or frame navigation.

valueGrammar string

The ABNF production the directive's value follows.

example: serialized-source-list

fallbackChain string[]

The ordered §6.8.3 fallback list, most relevant first, including the directive itself. Just [name] for the directives §6.8.3 does not cover — which includes script-src, style-src, child-src and every non-fetch directive.

example: ["frame-src","child-src","default-src"]

fallbackParent string nullable

The next name after this one in fallbackChain, or null.

example: child-src

destinations string[]

Fetch request destinations for which §6.8.1 returns exactly this name. Empty for every directive reached only as a fallback (child-src, script-src, style-src) and for the non-fetch directives.

example: ["frame","iframe"]

ignoredInMeta boolean

Whether a <meta>-delivered policy ignores this directive (§3.3: report-uri, frame-ancestors and sandbox).

example: false

ignoredInReportOnly boolean

Whether a report-only policy ignores it (§6.3.2: sandbox only).

example: false

consultsNonce boolean

Whether this directive's own pre-request check consults the request's cryptographic nonce metadata (§6.7.2.3) — directly for the script and style directives, and for default-src through the check it delegates to (§6.1.3.1). False for the two attribute directives, which have an inline check and no pre-request check.

example: false

consultsIntegrity boolean

Whether it consults the request's integrity metadata (§6.7.2.4). The script element directives only, plus default-src by delegation.

example: false

honorsStrictDynamic boolean

Whether 'strict-dynamic' changes the URL matching this directive performs (§6.7.1.1): true for script-src, script-src-elem and default-src, false for every other directive — in img-src the keyword is inert. /evaluate narrows this per policy, because default-src only reaches the script check when no script directive is declared.

example: false

ianaRegistered boolean

Whether the name appears in the pinned IANA Content Security Policy Directives registry snapshot (last updated 2023-02-03). The registry still holds only the sixteen CSP Level 2 names, so most CSP3 additions are false.

example: true

specSection string

Section number in the document that defines it.

example: 6.1.5

specUrl string

Deep link to that section.

example: https://www.w3.org/TR/CSP3/#directive-frame-src

Documented examples

Build-generated requests and complete responses
2
What does frame-src fall back to?
GET /api/csp/lookup?name=frame-src
{
  "data": {
    "name": "frame-src",
    "type": "fetch",
    "status": "csp3",
    "statusNote": null,
    "governs": "Requests that populate a child navigable, such as an iframe or frame navigation.",
    "valueGrammar": "serialized-source-list",
    "fallbackChain": [
      "frame-src",
      "child-src",
      "default-src"
    ],
    "fallbackParent": "child-src",
    "destinations": [
      "frame",
      "iframe"
    ],
    "ignoredInMeta": false,
    "ignoredInReportOnly": false,
    "consultsNonce": false,
    "consultsIntegrity": false,
    "honorsStrictDynamic": false,
    "ianaRegistered": true,
    "specSection": "6.1.5",
    "specUrl": "https://www.w3.org/TR/CSP3/#directive-frame-src"
  },
  "meta": {
    "endpoint": "csp",
    "route": "/lookup",
    "params": {
      "name": "frame-src"
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Look up worker-src
GET /api/csp/lookup?name=worker-src
{
  "data": {
    "name": "worker-src",
    "type": "other",
    "status": "csp3",
    "statusNote": null,
    "governs": "Scripts loaded as a dedicated worker, shared worker or service worker. Its own check is a plain source-list match, so a nonce or 'strict-dynamic' written into worker-src itself does nothing.",
    "valueGrammar": "serialized-source-list",
    "fallbackChain": [
      "worker-src",
      "child-src",
      "script-src",
      "default-src"
    ],
    "fallbackParent": "child-src",
    "destinations": [
      "serviceworker",
      "sharedworker",
      "worker"
    ],
    "ignoredInMeta": false,
    "ignoredInReportOnly": false,
    "consultsNonce": false,
    "consultsIntegrity": false,
    "honorsStrictDynamic": false,
    "ianaRegistered": false,
    "specSection": "6.2.2",
    "specUrl": "https://www.w3.org/TR/CSP3/#directive-worker-src"
  },
  "meta": {
    "endpoint": "csp",
    "route": "/lookup",
    "params": {
      "name": "worker-src"
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

About this API

Coverage & behavior

Evaluates the Content-Security-Policy you paste into the query string. Nothing is fetched: not your origin, not the resource, not a report endpoint, not the specification. It is pure string and set logic over the values you supply, so it runs in CI, offline, and against a server that does not exist yet.

/check is the route to reach for first. It answers "would this policy allow this URL, and which directive decided?" — the two questions a blocked console message never answers precisely. It resolves the effective directive for the request's destination (CSP3 §6.8.1), walks the §6.8.3 fallback chain, and reports which single directive executed: §6.8.4 lets only the first declared name in the chain run, and every other directive defers. So with both default-src and script-src present, script-src executes and default-src reports executed: false — not "both applied". Then it runs the executing directive's own pre-request check and returns the expression that matched, or the exact production each expression failed at.

The fallback chains are the facts most worth knowing, and they are transcribed from §6.8.3 rather than guessed: frame-src → child-src → default-src; worker-src → child-src → script-src → default-src; script-src-elem → script-src → default-src. And the ones that do not exist: base-uri, form-action, frame-ancestors, sandbox, webrtc and the reporting directives never fall back to default-src. §6.1.3's own equivalence example omits all of them, and §6.4.2 states outright that default-src 'none' still allows the resource to be embedded by anyone. /check?context=form-action proves it in one request.

'strict-dynamic' is the other answer people come looking for, and §6.7.1.1's step order is normative and non-obvious: nonce, then integrity, then 'strict-dynamic', then the source list. A parser-inserted <script src> with a matching nonce is therefore allowed even alongside 'strict-dynamic'; without a nonce it is blocked even when its host is allowlisted. Flip parserInserted — which defaults to true, modelling a script tag written in the HTML — and watch the answer change. The keyword is also inert outside the script check: in img-src it does nothing, and in default-src it only bites when no script directive is declared. Even a worker is subtle, because worker-src's own check is a plain source-list match while script-src's is the script check. §6.7.1.1 gates its whole nonce/integrity/'strict-dynamic' block on the request's destination being script-like, and Fetch's script-like list has six entries — audioworklet, paintworklet, script, serviceworker, sharedworker, worker — while asking algorithms that use it to consider xslt as well, because that too can execute script. This API takes Fetch up on that, so context=xslt is treated as script-like and the nonce, integrity and 'strict-dynamic' steps apply to an XSLT stylesheet. A literal six-name reading would give it plain source-list matching instead; that is the one place this API goes beyond the letter of the two specs, and it is the safer of the two readings.

/parse runs the §2.2.1 parse algorithm and shows you its results: directive names lowercased, a repeated name kept once and every later occurrence discarded, empty and non-ASCII tokens skipped, and every source expression classified against the §2.3.1 grammar with its scheme, host, port, path, hash algorithm or base64 value pulled apart. /evaluate returns a coverage table — for each of the fifteen protection surfaces, which directive governs it after the fallback chain and whether inline content is allowed — plus ranked findings, each citing the clause it rests on.

There is deliberately no grade, no score and no pass/fail badge. Not "not yet" — never. Findings carry a severity that is this API's own documented ranking of how much protection the condition removes; it is not a CVSS score and not a vulnerability rating, and a policy with zero findings is not an audit. CSP is a defence-in-depth mitigation against injection, not an authorization mechanism.

Asymmetries that look like bugs and are not. Scheme matching upgrades only upwards: http: matches https:, ws: matches wss:, http: and https:, and nothing matches downward. *.example.com matches www.example.com and a.b.example.com and not the apex example.com. example.com. with a trailing dot is compared literally. 'none' is honoured only while it is the sole expression, so script-src 'none' https://example.com really does match https://example.com/, while a valueless script-src matches nothing at all. A path-part is dropped entirely once redirectCount is not zero — a deliberate compromise against cross-origin path leaks (§7.6). And a host-source never matches a URL with no host, which is why img-src 'self' blocks a data: image and img-src data: allows it.

Where the pinned draft contradicts itself, this API follows the normative algorithm, says which one it followed, and reports both readings in ambiguities — it never silently picks a side and never claims what a browser does. There are exactly three such places, each with two citable conflicting passages: whether a host-source can match an IP-literal host, whether http://example.com:80 matches https://example.com/, and what 'unsafe-allow-redirects' means. Growing that list needs a new citation, not a hunch.

Scope, stated plainly rather than discovered later. No network, ever. No inline-content checking and no hash computation: matching an inline script or style against a hash-source needs SHA-256/384/512 over the source, which on this runtime means the asynchronous crypto.subtle API, and these handlers are synchronous. /evaluate still answers the §6.7.3.2 question "does this source list allow all inline behaviour?", because that needs no hashing, and /check accepts URLs only. Resource-hint requests (prefetch, prerender) use a different union-of-all-source-lists rule and are out of scope, so they are not context values. There is no separate post-request route: model a redirect chain by passing the final URL with redirectCount set. Opaque origins and §7.8 policy inheritance into blob:, data: and srcdoc documents are not modelled, self=null is a 400, and 'self' compares the URL's own scheme/host/port tuple, so it will not match a blob: URL whose inner origin is yours. sandbox tokens are echoed, not validated — they come from HTML's iframe attribute, not from CSP. There is no referrer row, because no current W3C Recommendation or draft defines it, and no embedded-enforcement directives. A source expression containing a comma cannot be expressed, exactly as on the wire.

We model the pinned W3C draft, not any browser. Console wording, vendor quirks, Reporting-Endpoints plumbing and CSP Level 2-only behaviour are out of scope, and browsers differ from the draft and from each other. The directive table is pinned to CSP Level 3 Working Draft 2026-07-29 by SHA-256 and cross-checked against the IANA registry, and scripts/refresh-csp-directives.mjs --check re-derives the mechanical columns from the live documents and fails on drift. Facts verified 2026-07-30.

Use it for

  • Find out which directive blocked a script when the console only says the policy did
  • Prove that default-src 'none' still lets a form post to any origin
  • Assert in CI that a policy allows your CDN before you ship the header
  • Explain to a reviewer why 'strict-dynamic' makes a host allowlist irrelevant
  • Look up what frame-src falls back to without reading the specification

Frequently asked questions

Does default-src cover base-uri and form-action?

No. default-src is a fallback for fetch directives only; base-uri, form-action, frame-ancestors and sandbox are absent from the CSP3 §6.8.3 fallback lists, so default-src 'none' alone still allows a form post to any origin. /check?context=form-action proves it.

Why does 'strict-dynamic' block my CDN script?

In a script directive 'strict-dynamic' short-circuits URL matching: a parser-inserted <script src> is blocked and a createElement-inserted one is allowed, whatever your host allowlist says (§6.7.1.1). Flip parserInserted and watch the answer change.

Does 'unsafe-inline' still work if I also use a nonce?

No. Any nonce-source or hash-source in the same directive makes 'unsafe-inline' inert (§6.7.3.2). /evaluate reports that as info, not as a weakness — it is the documented backwards-compatibility pattern.

What does frame-src fall back to?

frame-srcchild-srcdefault-src, and worker-srcchild-srcscript-srcdefault-src. /check returns the full chain it walked plus which single entry executed.

Does this API grade or score my CSP?

Deliberately not. There is no A+…F grade and no numeric score. /evaluate returns findings with a documented severity and the exact CSP3 clause each one rests on; a policy with zero findings is not an audit.

Does this API fetch my website?

Never. It evaluates only the policy string in your query, so it runs from CI, offline and against a server that does not exist yet.

Standards & references