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 |
| Syntax | JSON object per group | Structured-field name and URL pairs |
| URLs per name | Several, with weights and failover | Exactly one |
| Scope | Cached for max_age across responses | The response it is served on |
| Browser support | Chromium only | Chrome, 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 for | NEL, and nothing else | Everything 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-Endpointsheader (modern, declares endpoints) - the
Report-Toheader (deprecated, declares endpoints) - the CSP
report-todirective (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.

Next steps
- Wire up the modern header in how to set up the Reporting API.
- Read about the network-error stream in what is NEL.
- See the network-error report.
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.