All posts

Report-To vs Reporting-Endpoints, migrate off the deprecated header

CentralCSP Team ·

Last update:

There are two generations of the HTTP header that tells the browser where to send reports, and copy-pasting the wrong one from an old tutorial is a common way to end up with reports that silently never arrive. Report-To came first and is now deprecated. Reporting-Endpoints replaced it and is simpler. For almost everything you should use Reporting-Endpoints; the one exception, Network Error Logging, still needs the old header. Here is what changed and how to move across.

This is the header-level version of the report-uri vs report-to story, which is about the CSP directives. Different layer, same direction of travel: the platform is consolidating onto one reporting mechanism.

The two headers side by side

Report-To (v0) declares endpoint groups as JSON, with several URLs per group, a caching lifetime, and load-balancing weights. It is expressive, and that expressivity is exactly what never got standardized.

Report-To: { "group": "csp-endpoint", "max_age": 10886400,
             "endpoints": [ { "url": "https://<Endpoint-ID>.report.centralcsp.com" } ] }

Reporting-Endpoints (v1) declares plain name and URL pairs, one URL each, scoped to the response it is served on. No groups, no caching, no failover, just a name mapped to a URL.

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

A policy references the name the same way in both generations: report-to csp-endpoint in CSP, or a report-to="csp-endpoint" parameter on COOP and COEP. So migrating is mostly a matter of swapping the header that declares the endpoint, not the policies that use it.

Report-To (v0)Reporting-Endpoints (v1)
Status❌ Deprecated, non-standard✅ The W3C Reporting API standard
SyntaxJSON object per groupStructured-field name and URL pairs
URLs per nameSeveral, with weights and failoverExactly one
ScopeCached for max_age across responsesThe response it is served on
Browser supportChromium onlyChrome, Edge, Firefox, Safari
Carries CSP, COOP, COEP, deprecation, intervention, crash✅ Yes✅ Yes
Carries Network Error Logging (NEL)✅ Yes❌ No, NEL still requires v0
Use it forNEL, and nothing elseEverything else

What changed and why

The W3C Reporting specification defines only Reporting-Endpoints. Report-To was a Chromium-era mechanism that never became a standard, which is why MDN marks it both deprecated and non-standard, and why it only ever shipped in Chromium browsers. v1 dropped the grouping, caching, and load-balancing model in favor of a simpler, per-response header that other browser engines were willing to adopt. That simpler header is already cross-browser and works across current browsers, including Chrome, Edge, Firefox, and Safari. Full detail is on the Report-To vs Reporting-Endpoints reference.

The four-way report-to confusion

Most of the pain here is naming. The phrase "report-to" shows up in four different places, and people wire the wrong two together. Keep them straight:

  • the Reporting-Endpoints header (modern, declares endpoints)
  • the Report-To header (deprecated, declares endpoints)
  • the CSP report-to directive (names an endpoint from inside a policy)
  • the report-to= parameter on COOP and COEP headers (names an endpoint for that policy)

The directive and the parameter both just reference a name; that name has to be declared by one of the two headers on the same response.

The one case you still need Report-To

Network Error Logging (NEL) is the holdout. It is not supported by Reporting-Endpoints: the NEL header names a group that must be defined in a Report-To header. Until a replacement exists, any site using NEL keeps Report-To around for that purpose only. Everything else, CSP, COOP, COEP, deprecations, interventions, crashes, should move to Reporting-Endpoints.

How to migrate

The migration is low-risk because the two headers do not conflict, and with Reporting-Endpoints already cross-browser there is no reason to wait. Send Reporting-Endpoints everywhere, and keep Report-To only on the responses that also send the NEL header. If you want to be cautious during the switch, send both for a while and confirm reports still arrive before removing the old one. For more on where browser reports go and how to receive them, CentralCSP accepts reports from both headers at one endpoint, so you can transition gradually without a gap in your data.

The three delivery methods as tabs, with Reporting-Endpoints selected

Next steps

Because NEL keeps you on both headers for now, the practical outcome is two declarations pointing at one collector. A CentralCSP website gives you a single reporting endpoint URL to name in both, so the v0 and v1 streams land in the same place and you are not reconciling two report stores while the migration finishes.

Collect every report type at one endpoint.

Sources