# Report-Only (/en/docs/web-security/policies/content-security-policy/report-only)



The `Content-Security-Policy-Report-Only` header tells the browser to check a
Content Security Policy (CSP) and report every violation, without blocking
anything. You see exactly what a policy would break before it breaks it. That
makes it the safe way to roll out or tighten a policy on a live site.

A candidate policy under test, paired with the endpoint that receives its reports:

```http
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
```

```http
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint
```

## Quick overview [#quick-overview]

A Report-Only policy is written exactly like an enforced one. The only difference
is the header name and the resulting disposition. With
`Content-Security-Policy-Report-Only` the disposition is `report`, so the browser
loads the resource and sends a [CSP violation report](/en/docs/web-security/reporting-api/reports/csp-violation)
instead of applying the [`Content-Security-Policy`](/en/docs/web-security/policies/content-security-policy)
header's `enforce` behavior.

```http
Content-Security-Policy-Report-Only:
    default-src 'self';
    script-src 'self' 'nonce-r4nd0m';
    object-src 'none';
    base-uri 'none';
    report-to csp-endpoint
```

A report-only policy is useful only if it has somewhere to send reports. Pair it
with a [`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)
directive (and the legacy [`report-uri`](/en/docs/web-security/policies/content-security-policy/directives/report-uri)
only if you need to cover old browser versions) so the violations reach an
endpoint you control.

## Values [#values]

The header value is a CSP, the same semicolon-separated list of directives you
would put in an enforced policy. Every CSP directive is valid here. The directives
that actually matter in Report-Only are the reporting ones, since nothing is
enforced.

| Part                                                                                         | Status        | What it does                                                            |
| -------------------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------- |
| The directive list                                                                           | ✅ Good        | Defines the policy the browser evaluates against the page.              |
| [`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)   | ✅ Good        | Names the endpoint group that receives violation reports.               |
| [`report-uri`](/en/docs/web-security/policies/content-security-policy/directives/report-uri) | ⚠️ Deprecated | Legacy reporting target, kept only for old, unupdated browser versions. |

A response can carry both headers at once. Send an enforced
`Content-Security-Policy` for the policy you trust today, and a separate
`Content-Security-Policy-Report-Only` for the stricter policy you are testing. The
browser evaluates each independently and reports the report-only one without
touching the page.

## Insecure values to avoid [#insecure-values-to-avoid]

A Report-Only policy never protects anything, so it has no insecure values of its
own. The mistake is treating it as protection. Shipping only
`Content-Security-Policy-Report-Only` in production means the browser reports
attacks but blocks none of them. An attacker's inline script still runs. Use
Report-Only to learn what to enforce, then move the validated policy to the
enforcing `Content-Security-Policy` header.

A second mistake is a report-only policy with no reporting directive at all. With
no `report-to` or `report-uri`, the browser evaluates the policy and discards
every violation, so you learn nothing.

## Why this header exists [#why-this-header-exists]

A real policy almost always breaks something on the first try: an inline script,
a third-party widget, a `data:` image. Enforcing an untested policy takes the site
down. Report-Only was introduced so you can deploy a candidate policy, watch the
violations roll in from real traffic, fix the gaps, and only then enforce it. It
turns CSP rollout from a guess into a measurement.

## What it protects against [#what-it-protects-against]

The header itself blocks nothing, so it protects nothing directly. Its security
value is indirect. It lets you reach a strict, enforced
[`Content-Security-Policy`](/en/docs/web-security/policies/content-security-policy)
safely. The faster you can validate a tight policy, the sooner you get real
protection against cross-site scripting (XSS) and injection. Collecting the
report-only violations in [CentralCSP](/platform/csp-builder) shows you exactly which
directives to adjust before you flip to enforcement.

## Known bypasses and limitations [#known-bypasses-and-limitations]

A `<meta http-equiv>` tag cannot deliver a Report-Only policy. The meta element
only supports the enforcing `Content-Security-Policy`, so Report-Only is an HTTP
response header exclusively. The same applies to the reporting directives
(`report-to`, `report-uri`), which a meta tag also cannot set.

Report-Only violations are reported per policy, so a noisy candidate policy can
generate a large volume of reports on a high-traffic page. Sample and triage them
rather than reading raw JSON.

## Risks of misconfiguration [#risks-of-misconfiguration]

The dominant risk is confusing the two headers. Leaving a strict policy in
Report-Only forever gives a false sense of security with zero enforcement, while
promoting an untested policy straight to `Content-Security-Policy` breaks the
page. Validate in Report-Only, then enforce.

## Recommendation [#recommendation]

Whenever you tighten a policy, run the candidate in Report-Only alongside the
enforced one, and point both at `report-to` with a
[`Reporting-Endpoints`](/en/docs/web-security/reporting-api/headers/reporting-endpoints)
declaration.

```http
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
```

```http
Content-Security-Policy-Report-Only:
    script-src 'nonce-r4nd0m' 'strict-dynamic';
    object-src 'none';
    base-uri 'none';
    report-to csp-endpoint
```

Every current engine delivers `report-to` reports now, so this pair is the
primary transport; add `report-uri` only for old-version tails. Staged rollout
through Report-Only is the approach the
[web.dev strict CSP guide](https://web.dev/articles/strict-csp) recommends.

## How to set it up [#how-to-set-it-up]

1. Send `Content-Security-Policy-Report-Only` with your candidate policy and a
   [`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)
   directive that names an endpoint group.
2. Declare that group with the [`Reporting-Endpoints`](/en/docs/web-security/reporting-api/headers/reporting-endpoints)
   header so the browser knows where to send reports.

```http
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
```

```http
Content-Security-Policy-Report-Only:
    default-src 'self';
    script-src 'self' 'nonce-r4nd0m';
    object-src 'none';
    base-uri 'none';
    report-to csp-endpoint
```

3. Watch the [CSP violation reports](/en/docs/web-security/reporting-api/reports/csp-violation),
   fix the legitimate breakages, and once the policy is clean, move it to the
   enforcing `Content-Security-Policy` header. The
   [Reporting API configuration checker](/tools/reporting-api) confirms your
   endpoint wiring works before you rely on the reports.

## Browser support [#browser-support]

Widely supported. `Content-Security-Policy-Report-Only` works across modern
browsers. The `report-to` plus
[`Reporting-Endpoints`](/en/docs/web-security/reporting-api/headers/reporting-endpoints)
transport is now cross-browser too, supported in current Chrome, Safari, and
Firefox (Firefox was the last engine to add it). Keep `report-uri` only to cover
old, unupdated browser versions.

## See also [#see-also]

* [Content-Security-Policy](/en/docs/web-security/policies/content-security-policy)
* [report-to directive](/en/docs/web-security/policies/content-security-policy/directives/report-to)
* [report-uri directive](/en/docs/web-security/policies/content-security-policy/directives/report-uri)
* [Reporting-Endpoints header](/en/docs/web-security/reporting-api/headers/reporting-endpoints)
* [CSP violation report](/en/docs/web-security/reporting-api/reports/csp-violation)
* [CSP enforce vs report-only](/en/blog/csp-enforce-vs-report-only)
* [report-uri vs report-to](/en/blog/report-uri-vs-report-to)

## Sources [#sources]

* [MDN, Content-Security-Policy-Report-Only](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy-Report-Only)
* [W3C, Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)
* [W3C, Reporting API](https://www.w3.org/TR/reporting-1/)
