Content-Security-Policy Generator & Checker
Build a Content-Security-Policy header directive by directive, or paste one to check it: see which directive governs each resource, get warnings, and test whether a URL would load.
How to Use
- Choose Build to write a policy field by field, or Check to paste one (a bare policy, a whole header line, or a meta tag).
- In Build, click a directive’s field, then use the chips (
'self',https:, a fresh nonce…) or type sources separated by spaces. - Read the directive map: each resource type shows the directive that decides it, including fallbacks to
default-src. - Work through the warnings, highest first. Each one names the directive and what to change.
- Type a URL and pick its type under Would this load? to see the verdict and, in Show Work, every source it was compared with.
- Pick the output style (header, meta tag, Apache, Nginx or PHP) and press Copy.
—
Worked Example
A page on https://example.com sends:
default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; img-src 'self' data:; object-src 'none'; base-uri 'self'
1. https://cdn.jsdelivr.net/npm/x.js as a script: script-src is present, 'self' fails (different host), https://cdn.jsdelivr.net matches scheme, host and default port. Allowed.
2. https://evil.example/x.js as a script: neither source matches. Blocked.
3. https://fonts.gstatic.com/s/inter.woff2 as a font: there is no font-src, so default-src 'self' decides. Blocked — the usual reason web fonts vanish after a CSP goes live.
4. A data: image: img-src lists data:. Allowed. The same data: URL as a script is blocked, because script-src does not list it.
The common mistake: leaving out the quotes. default-src self does not mean the page’s own origin; it allows a host literally called “self”, so the site blocks its own scripts. Keywords ('self', 'none', 'unsafe-inline', nonces and hashes) always take single quotes; hosts and schemes never do. The second mistake is adding 'unsafe-inline' to script-src to silence errors, which lets injected scripts run and removes most of the protection.
Show Work
Reference
From Allowlists to Nonces
Content Security Policy began at Mozilla, where Brandon Sterne led the design, and first shipped in Firefox 4 in 2011 under the prefixed header X-Content-Security-Policy; Chrome and Safari briefly used X-WebKit-CSP. The W3C published the unprefixed header as CSP 1.0, a Candidate Recommendation, in 2012, and CSP Level 2, which added nonces, hashes, frame-ancestors and base-uri, became a W3C Recommendation in 2016. CSP Level 3 is still a working draft but is what current browsers implement.
Early policies were long host allowlists, and in 2016 Google researchers analysed policies collected from across the web in the paper “CSP Is Dead, Long Live CSP!”, finding that about 95% of the distinct policies could be bypassed — mostly through 'unsafe-inline', wildcards, or allowed hosts that serve JSONP endpoints or old Angular libraries. The same paper introduced 'strict-dynamic', and nonce-based “strict CSP” has been the recommended approach since.
About This Tool
This tool writes a Content-Security-Policy from one field per directive, with chips for common sources and freshly generated nonces, and outputs it as a header line, a meta tag, or Apache, Nginx and PHP code. In Check mode it reads a pasted policy, header line or meta tag the way a browser does, maps every resource type to the directive that governs it, flags risky or broken sources, and answers whether a given URL would load, listing each source it tried.
The matching follows the CSP Level 3 rules for schemes, wildcard hosts, ports, paths, 'self' and 'strict-dynamic'; browsers can still differ at the edges, so confirm a new policy in report-only mode first. Policies and test URLs stay in your browser and are never sent or stored.
It suits developers adding a first policy, teams tightening one, and anyone decoding a “Refused to load” console error.
Related tools: .htaccess Generator, Hash Generator, and Meta Tag & Open Graph Generator.
Frequently Asked Questions
Should the policy go in a header or a meta tag?
A header whenever you can. A <meta http-equiv> policy cannot use frame-ancestors, report-uri, report-to or sandbox, cannot be report-only, and only covers content that comes after the tag. The meta tag is for hosts where you cannot set headers, such as some static-site services.
Why did my fonts or images break after adding default-src 'self'?
Every fetch type without its own directive falls back to default-src. With default-src 'self' alone, a Google Fonts page needs style-src 'self' https://fonts.googleapis.com and font-src https://fonts.gstatic.com, and inline data: images need img-src 'self' data:. The directive map shows which types are riding on the fallback.
What does 'strict-dynamic' do?
It lets a script that was trusted by its nonce or hash load further scripts, and makes the browser ignore host lists, https: and 'self' for scripts. That is the basis of Google’s recommended “strict CSP”: script-src 'nonce-…' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none'. Newer browsers use the nonce; older ones fall back to the https: and unsafe-inline parts.
How do I try a policy without breaking the site?
Send it as Content-Security-Policy-Report-Only with a report-uri (and report-to) endpoint. Nothing is blocked; violations are reported and shown in the browser console. When a week of real traffic produces only reports you expect, switch the header name to Content-Security-Policy.
Should I use a nonce or a hash for inline scripts?
A nonce suits pages your server builds: a new random value of at least 128 bits on every response, in the header and in each <script nonce>. A hash suits fixed inline code on static pages: the Base64 SHA-256 of the exact script text, so alert(1) becomes 'sha256-bhHHL3z2vDgxUt0W3dWQOrprscmda2Y5pLsLg4GF+pI='. One changed space changes the hash.
How do I use the Content-Security-Policy Generator & Checker?
Just pick your options. The answer shows up right away — there is no button to press. Change anything and it updates by itself.
Is it free? Does it work without internet?
Yes to both. It is free with no sign-up, and once the page has loaded it keeps working even with no internet.
Where does my data go?
Nowhere — every calculation runs on your own device. Nothing you enter is uploaded, logged, or stored.
Common Use Cases
Adding analytics
Google Analytics 4 needs https://*.googletagmanager.com in script-src and https://*.google-analytics.com in connect-src and img-src.
Reading console errors
Paste the policy and the URL from “Refused to load the script …” to see which directive refused it and which source would allow it.
Auditing another site
Copy the header from the browser’s Network panel into Check mode to see its fallbacks, missing object-src or base-uri, and wildcard sources.
Locking down an admin area
Start from default-src 'none', add back 'self' for scripts, styles, images and connect, and set base-uri, form-action and frame-ancestors: 152 bytes of header.
Rolling out safely
Build the policy, tick Report-only, deploy, and read the reports before enforcing it.
Last updated: