# report-uri vs report-to, and how to migrate (/en/blog/report-uri-vs-report-to)





If you have a Content Security Policy (CSP), you have probably seen both `report-uri`
and `report-to` in examples and wondered which one is correct. The short answer:
`report-to` is the modern directive and `report-uri` is deprecated. The
`Reporting-Endpoints` header is already cross-browser, and the CSP `report-to`
directive recently became cross-browser too, so you can use `report-to` for modern
browsers and keep `report-uri` only as a fallback for very old ones. This post explains the difference,
why both exist, and gives you a policy you can copy.

## The one-line difference [#the-one-line-difference]

`report-uri` points a CSP straight at a URL. `report-to` points a CSP at a named
endpoint that is declared separately, in the `Reporting-Endpoints` header, which is
part of the [Reporting API](/en/docs/web-security/reporting-api). Same goal, getting violation
reports to your server, but different plumbing: one is self-contained, the other
splits the destination out into a reusable, named endpoint.

<CodeBlockTabs defaultValue="report-uri">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="report-uri">
      report-uri
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="report-to">
      report-to
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="report-uri">
    ```http
    Content-Security-Policy: default-src 'self'; report-uri https://<Endpoint-ID>.report.centralcsp.com
    ```
  </CodeBlockTab>

  <CodeBlockTab value="report-to">
    ```http
    Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
    Content-Security-Policy: default-src 'self'; report-to csp-endpoint
    ```
  </CodeBlockTab>
</CodeBlockTabs>

The indirection in the second form is deliberate. Because the endpoint is named and
declared once, every policy on the page (CSP, COOP, COEP, and the rest) can point at
the same endpoint, and the browser can manage delivery for all of them through one
mechanism.

|                                          | `report-uri`                             | `report-to`                                     |
| ---------------------------------------- | ---------------------------------------- | ----------------------------------------------- |
| Status                                   | ❌ Deprecated                             | ✅ Current                                       |
| Destination                              | A URL, inline in the policy              | A name declared in `Reporting-Endpoints`        |
| Content type posted                      | `application/csp-report`                 | `application/reports+json`                      |
| Payload shape                            | One report wrapped in `csp-report`       | A batch of reports, each with `type` and `body` |
| Batches multiple reports                 | ❌ No, one POST per violation             | ✅ Yes                                           |
| Shared with COOP, COEP, NEL, deprecation | ❌ No, CSP only                           | ✅ Yes, one endpoint for all                     |
| Browser support                          | Everywhere, including old browsers       | Chrome, Edge, Firefox, Safari                   |
| Keep it because                          | It is the fallback for very old browsers | It is where everything is going                 |

Send both. Browsers that understand `report-to` ignore `report-uri`, so the pair costs
you nothing and covers every browser.

## Why report-uri is deprecated [#why-report-uri-is-deprecated]

`report-uri` came from the era when CSP was the only thing that reported. It posts a
single JSON object wrapped in a `csp-report` key, with `Content-Type:
application/csp-report`. That worked, but every new policy that wanted reporting
would have needed its own bespoke directive and its own payload shape.

The Reporting API replaced that with one model for the whole platform: one header to
declare endpoints, one delivery format for every report type, and a per-policy way
to name an endpoint. That is why the
[`report-to` directive](/en/docs/web-security/policies/content-security-policy/directives/report-to)
plus `Reporting-Endpoints` superseded the standalone directive. The payloads even
differ in casing: the legacy form uses kebab-case (`blocked-uri`,
`effective-directive`), and the modern
[`csp-violation` report](/en/docs/web-security/reporting-api/reports/csp-violation) uses camelCase
(`blockedURL`, `effectiveDirective`). An endpoint that accepts both must branch on
the `Content-Type`.

## Why report-uri is now just a fallback [#why-report-uri-is-now-just-a-fallback]

For a long time the practical advice was to send both, because the CSP `report-to`
directive delivery only worked in Chromium. That changed: the `Reporting-Endpoints`
header has been cross-browser for a while, and the CSP `report-to` directive recently
became cross-browser too, so it now works across current browsers, including Chrome,
Edge, Firefox, and Safari. So `report-to` alone covers modern traffic.

The two still coexist safely. Browsers that understand `report-to` ignore
`report-uri` when both are present, so they never double-report. That makes
`report-uri` a clean fallback: keep it only if you need to cover very old, unupdated
browsers that predate this cross-browser support.

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

```http
Content-Security-Policy:
    default-src 'self';
    report-uri https://<Endpoint-ID>.report.centralcsp.com;
    report-to csp-endpoint
```

If you do not need to support those old browsers, you can drop `report-uri` and send
`report-to` on its own. Keeping both costs nothing and loses no reports.

## Do not confuse the two report-to meanings [#do-not-confuse-the-two-report-to-meanings]

The phrase "report-to" is overloaded, which is most of the confusion. There is the
CSP `report-to` *directive* (used above, inside the policy) and a `Report-To`
*HTTP header* (the deprecated first-generation reporting header, now replaced by
`Reporting-Endpoints`). They are different things at different layers. The header
comparison is covered in
[Report-To vs Reporting-Endpoints](/en/docs/web-security/reporting-api/concepts/report-to-vs-reporting-endpoints);
this post is about the CSP directive.

## Looking for a report-uri alternative [#looking-for-a-report-uri-alternative]

If you are searching for a `report-uri` replacement, you are usually not looking for
a different directive, you are looking for [where browser reports go and how to receive them](/en/blog/where-to-send-csp-reports) without
building and running a collector. That is the real cost: receiving the POSTs is
easy, but storing, de-duplicating, grouping, and acting on them is a service in its
own right.

CentralCSP is that hosted endpoint. It accepts both the legacy
`application/csp-report` object and the modern `application/reports+json` array,
[normalizes them into one model](/en/docs/platform/monitoring), groups
violations by directive and blocked host, and turns them into alerts and evidence.
Point both directives at it and you are done.

<img alt="The three delivery methods as tabs, with Reporting-Endpoints selected" src="__img0" width="1359" height="645" />

## Next steps [#next-steps]

* Set reporting up end to end in [Get started with CSP reporting](/en/blog/get-started-csp-reporting).
* Read the field meanings in [the CSP violation report](/en/docs/web-security/reporting-api/reports/csp-violation).
* Score your policy with the [CSP evaluator](/tools/csp-evaluator).

Sending both directives means your collector has to accept two payload shapes, the
single `csp-report` object and the batched `reports+json` array, and treat them as the
same violation rather than as two. A CentralCSP endpoint parses both formats and
normalises them into one report stream per site, so keeping the fallback around does not
split your data in half.

[Start collecting CSP reports](/register).

## Sources [#sources]

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