CSP violation report fields
When a Content Security Policy blocks something, the browser can send a JSON
violation report to an endpoint. Two formats exist: the legacy report-uri
(csp-report) body and the modern Reporting API (report-to). This reference
lists every field in both, with meaning and source, plus a live filter.
How it works
A page declares where to send reports, then the browser POSTs JSON on a
violation. The legacy format wraps fields in a csp-report object:
{
"csp-report": {
"document-uri": "https://app.example/page",
"violated-directive": "script-src 'self'",
"effective-directive": "script-src-elem",
"blocked-uri": "https://evil.example/x.js",
"disposition": "enforce",
"status-code": 200
}
}
The Reporting API sends a report with type: "csp-violation" and a body
object whose keys are camelCase (documentURL, blockedURL,
effectiveDirective). The fields carry the same meaning across both formats.
The two mechanisms side by side
| Aspect | Legacy report-uri | Modern Reporting API (report-to) |
|---|---|---|
| CSP directive | report-uri https://... | report-to groupname |
| Supporting header | none needed | Reporting-Endpoints or Report-To |
| Body wrapper | { "csp-report": { … } } | { "type": "csp-violation", "body": { … } } |
| Key style | hyphenated (blocked-uri) | camelCase (blockedURL) |
| Batching | one POST per violation | browser may batch multiple reports |
| Browser support | all browsers | Chromium-based; Firefox partial |
During a migration, include both directives simultaneously. Older browsers will use report-uri; modern Chromium browsers will use report-to and the Reporting API.
Interpreting the most important fields
violated-directive / effectiveDirective: The policy directive that triggered the block — for example, script-src 'self'. This tells you which part of your CSP is too strict (or correctly catching an unexpected resource).
blocked-uri / blockedURL: What was blocked. For cross-origin resources this is usually the full URL. For inline scripts the value is the token inline; for eval() it is eval. The browser may truncate cross-origin URIs to just the origin (scheme + host + port) for privacy. A value of inline without a script-sample means you have an inline script not covered by a nonce or hash.
source-file + line-number + column-number: The exact location in the page’s source where the violating markup appears. This is essential for finding the precise tag or script that triggered the report without scanning the entire document.
disposition: Either "enforce" (the resource was blocked) or "report" (the header was Content-Security-Policy-Report-Only — the resource was allowed but would have been blocked under an enforcing policy). This field lets you distinguish real blocks from policy-testing reports even when both arrive at the same endpoint.
A safe rollout workflow
- Start with
Content-Security-Policy-Report-Onlyand your intended policy. Setreport-urito a logging endpoint you control. - Monitor reports for a week. Most real apps have inline scripts, third-party analytics, or CDN resources that initially produce violations.
- Tighten or add exceptions (
'nonce-...','hash-...', additionalsrcvalues) until violations stop. - Switch to the enforcing
Content-Security-Policyheader when reports go quiet. - Keep
report-uriactive after going enforcing — new features or third-party updates can introduce violations at any time.
Tips and notes
- Trial new policies with
Content-Security-Policy-Report-Onlyfirst. - Send both
report-uriandreport-towhile clients migrate. blocked-urimay be coarsened to an origin or a token likeinline/eval.dispositiondistinguishes anenforceblock from areport(report-only).- Expect a flood of
inlineviolations on most real-world apps — they are often from third-party tag managers or analytics that inject scripts without nonces. - Some browsers sample or throttle reports to avoid overwhelming endpoints; design your log pipeline to accept bursts after deployments.