Content-Security-Policy-Report-Only: test a CSP without breaking your site (tested)
Report-Only runs a CSP in 'log, don't block' mode, so you can see what a policy would break before you enforce it. We compared it with the enforced header and the meta tag in Chrome.
1. Same policy, three ways
Policy: script-src 'self'; report-uri /csp-report, page with one inline <script>.
| Delivered as | Inline script | Report sent |
|---|---|---|
Content-Security-Policy-Report-Only header | Ran | Yes |
Content-Security-Policy header | Blocked | Yes |
<meta http-equiv="Content-Security-Policy-Report-Only"> | Ran | No: policy ignored |
For the meta tag Chrome said: The report-only Content Security Policy 'script-src 'self'' was delivered via a <meta> element, which is disallowed. The policy has been ignored. Report-only must be a real HTTP header.
2. What a report looks like
Chrome POSTed to report-uri with Content-Type: application/csp-report:
{"csp-report": {"document-uri": "http://127.0.0.1:8999/?m=ro", "referrer": "",
"violated-directive": "script-src-elem", "effective-directive": "script-src-elem", ...}}
The console message also printed the 'sha256-…' hash of the blocked inline script: copy it into script-src to allow exactly that script. Your endpoint must accept application/csp-report (not just application/json) or the reports are lost.
3. Rolling out a CSP
- Send the policy as Report-Only and collect reports for a few days of real traffic.
- Fix or allow what shows up (hashes, nonces, extra origins).
- Switch the header name to
Content-Security-Policy. You can keep a stricter Report-Only header next to it to test the next step.
# nginx
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; report-uri /csp-report" always;
Build the policy itself with the free security headers generator; our CSP example guide covers the directives.
Frequently asked questions
Does Content-Security-Policy-Report-Only block anything?
No. In our Chrome test the inline script ran; the violation was only logged and reported.
Can I use Content-Security-Policy-Report-Only in a meta tag?
No. Chrome ignored it with 'delivered via a <meta> element, which is disallowed'. Send it as an HTTP header.
What Content-Type do CSP reports use?
report-uri reports arrived as application/csp-report with a JSON body under 'csp-report'.
Can I send both CSP and CSP-Report-Only?
Yes; they are separate headers. Enforce the current policy and report-only a stricter one to test it.
Written with AI assistance. Measured on 2026-10-01 in Chromium 153 (full build): a page with one inline script was served with script-src 'self' as Content-Security-Policy-Report-Only, as enforced Content-Security-Policy, and as a report-only meta tag; a local endpoint logged the violation reports. The nginx line, the hash tip and running both headers side by side are from the CSP spec, not this test. PlainHeaders is our extension; the other methods are free.