Headers
The HTTP headers that deliver a Content Security Policy, enforce vs report-only, report-to vs report-uri, meta delivery limits, and how policies combine.
Last update:
A Content Security Policy (CSP) reaches the browser as an HTTP response header.
You send the policy on the response, the browser reads it, and from that point it
applies the rules to the page. This page covers the two delivery headers, how the
policy reports violations, the limits of <meta> delivery, and what happens when
a response carries more than one policy.
For the policy contents themselves, see the directives and the values they accept.
The enforcing header in its simplest form:
Content-Security-Policy: default-src 'self'Enforce vs report-only
There are two headers that deliver a policy. They take the exact same syntax; the only difference is what the browser does with a violation.
| Header | Status | What the browser does |
|---|---|---|
Content-Security-Policy | ✅ Good | Enforces the policy: blocks the violation and reports it. |
| Content-Security-Policy-Report-Only | ✅ Good | Reports the violation but does not block it. |
Report-only mode lets you watch what a policy would break before you turn it on. You deploy the policy on the report-only header, collect the reports, fix what the policy would have blocked, then move the same string to the enforcing header. A report-only policy needs a reporting endpoint to be useful, since reporting is all it does.
Content-Security-Policy-Report-Only:
default-src 'self';
report-to csp-endpointA response can carry both an enforcing policy and a report-only policy at once, which lets you enforce a known-good baseline while testing a stricter policy in parallel.
How the policy reports
A policy points the browser at an endpoint with one of two directives.
report-tonames a reporting group. The group's URL lives in a separate Reporting-Endpoints header, part of the Reporting API. This is the current mechanism. See the CSP report-to page.report-uriposts reports straight to a URL. It is the legacy mechanism and is ignored wherereport-tois supported, which is now every current browser (Chrome, Edge, Safari, and Firefox).
report-to is the primary mechanism; keep report-uri alongside it only to
cover old, unupdated browser versions. The modern Reporting-Endpoints header
pairs with report-to; the older
Report-To header is a separate,
deprecated mechanism that CSP no longer needs (it remains required only for NEL).
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"Content-Security-Policy:
default-src 'self';
report-uri https://<Endpoint-ID>.report.centralcsp.com;
report-to csp-endpointThe two delivery paths produce different report shapes: hyphenated field names
for report-uri and camelCase for report-to. Both land as a
CSP violation report, which
CentralCSP collects and normalizes. To confirm your endpoint is wired correctly,
run the Reporting API checker.
Delivery through a meta tag
You can also deliver a policy in HTML with a <meta> tag in the document
<head>, which is useful when you cannot set response headers.
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'">A <meta> policy is more limited than a header. It cannot do report-only. It
cannot use report-uri, report-to, frame-ancestors, or sandbox. It must
appear in the <head>, and it only governs content that comes after it in the
document. Prefer the HTTP header where you can set one.
How multiple policies combine
When a response carries more than one enforcing policy, the browser applies all of them, and a resource must satisfy every one to load. Policies combine by intersection, so the effective rule is the most restrictive across all of them.
This means adding a policy can only ever tighten the result, never loosen it. A
second policy of script-src 'self' will not re-allow a host that a first policy
of script-src 'none' already blocked. Each policy is also evaluated
independently for reporting, so one violation can produce reports to several
endpoints.
Recommendation
Run both headers together: enforce the policy you trust today, and test each
tightening step in a report-only policy before promoting it. Wire reporting
through report-to and
Reporting-Endpoints,
which every current browser now supports.
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"Content-Security-Policy:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
report-to csp-endpointContent-Security-Policy-Report-Only:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
connect-src 'self';
report-to csp-endpointStaged tightening with a report-only shadow policy is how the web.dev strict CSP guide recommends rolling a policy out, and it keeps a production incident out of every change.
FAQ
What is the difference between enforce and report-only CSP?
Content-Security-Policy blocks a violation and reports it;
Content-Security-Policy-Report-Only only reports it, so you can test a policy
before enforcing. See enforce vs report-only
for the full rollout workflow.
Can I set a CSP in a meta tag?
Yes for most directives, but a <meta http-equiv="Content-Security-Policy"> tag
cannot do report-only and ignores report-uri, report-to, frame-ancestors,
and sandbox. See meta tags vs headers for
when to use each.
See also
- What is CSP
- Content-Security-Policy-Report-Only
- report-to directive
- Reporting-Endpoints
- X-Frame-Options
- CSP violation report