# The Reporting-Endpoints header explained (/en/blog/reporting-endpoints-header)





The `Reporting-Endpoints` HTTP response header is how you tell the browser where to
send reports. You give each destination a name, then point your Content Security
Policy (CSP) and other policies at that name. One header, one place to declare every
endpoint, and the browser does the delivery.

This is the current way to wire up reporting on the web. It replaces the older
`Report-To` header, and it works with the CSP
[`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)
directive to collect violation reports, deprecation warnings, intervention reports,
and more.

This post is the practical wiring walkthrough. For the field-by-field spec
reference, see the
[Reporting-Endpoints header reference](/en/docs/web-security/reporting-api/headers/reporting-endpoints).

## What the Reporting-Endpoints header does [#what-the-reporting-endpoints-header-does]

The header carries a list of named endpoints. Each name maps to a single URL where
the browser can POST reports. Nothing reports anywhere on its own: a policy has to
reference an endpoint name before the browser sends anything to it.

Here is the smallest setup that collects CSP violations:

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

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

The first line declares an endpoint called `csp-endpoint`. The second line is a
normal CSP, and its
[`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)
directive names that endpoint. When the policy blocks something, the browser sends a
violation report to the URL behind `csp-endpoint`.

## Header syntax [#header-syntax]

Each entry is `name="url"`: an endpoint name, an equals sign, and the URL as a
quoted string. The browser resolves the URL against the response it came on.

You can declare several named endpoints in one header, separated by commas, and
route different report types to them by name:

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

Then a policy picks the name it wants:

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

A few rules worth knowing up front:

* Endpoint URLs must be potentially trustworthy, which in practice means HTTPS. A
  non-secure endpoint is silently ignored, not flagged as an error, so a typo in the
  scheme means reports quietly go nowhere.
* An endpoint in v1 is a single URL. There is no weighting, no priority, and no
  failover list, unlike the older `Report-To` groups.
* The endpoints you declare apply to the resource the header was sent with, not the
  whole origin.

## The default endpoint [#the-default-endpoint]

Some report types are not tied to a header that names an endpoint. Deprecation,
intervention, and crash reports go to an endpoint named `default` if you declare
one:

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

Despite the name, `default` is not a fallback for other endpoints. It is the
specific endpoint those untagged report types look for. If you do not declare a
`default` endpoint, the browser still generates those reports, but it has nowhere to
send them, so they are dropped.

## The CSP report-to directive [#the-csp-report-to-directive]

The [`report-to`](/en/docs/web-security/policies/content-security-policy/directives/report-to)
directive is the CSP side of this. Its value is an endpoint name, and that name must
exist in a `Reporting-Endpoints` header on the same response. The directive itself
carries no URL; it only references a name you declared in the header.

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

The directive is CSP Level 3 and is header-only. It does not work inside a `<meta>`
element, so this part of reporting has to be set as a real response header.

## report-to versus report-uri [#report-to-versus-report-uri]

The older directive is
[`report-uri`](/en/docs/web-security/policies/content-security-policy/directives/report-uri),
which takes a URL directly instead of an endpoint name. It is deprecated. Any browser
that understands `report-to` ignores `report-uri` entirely. [report-uri vs report-to](/en/blog/report-uri-vs-report-to) compares the two directives in full.

During the changeover you can specify both. The browser uses whichever it supports
and ignores the other, so you keep reports flowing from every visitor:

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

A browser with `report-to` support uses the endpoint name and ignores the
`report-uri` URL. A browser without it falls back to `report-uri`. Pair this with
the matching `Reporting-Endpoints` header so the endpoint name resolves.

## Where Report-To fits now [#where-report-to-fits-now]

The `Report-To` header is the predecessor of `Reporting-Endpoints`. It is both
deprecated and non-standard, and `Reporting-Endpoints` replaces it for new work.
See the
[Report-To header reference](/en/docs/web-security/policies/content-security-policy/directives/report-to)
for its history, and [Report-To vs Reporting-Endpoints](/en/blog/report-to-vs-reporting-endpoints)
for the migration in detail.

One practical exception: [Network Error Logging (NEL)](/en/blog/what-is-nel-network-error-logging) still relies on the legacy
`Report-To` header and is not covered by `Reporting-Endpoints` v1. If you collect NEL
reports, you keep sending `Report-To` for that case while using
`Reporting-Endpoints` for everything else.

## Browser support [#browser-support]

`Reporting-Endpoints` reached Baseline in 2024 and is widely supported across current
browsers. The CSP `report-to` directive has shipped in Chromium for years; its
cross-browser Baseline milestone lands in 2026 as the remaining engines catch up.
For new sites, write `Reporting-Endpoints` plus `report-to`, and add `report-uri`
only if you still need to cover older clients during a transition.

## Test before you trust it [#test-before-you-trust-it]

A silent-failure header rewards a quick check. The fastest way to confirm your setup
parses and resolves is the
[Reporting API checker](/tools/reporting-api), which reads your live response
headers and tells you whether the endpoint names and URLs line up.

When you are ready to start in safe mode, send the policy as a
[Report-Only header](/en/docs/web-security/policies/content-security-policy/report-only)
first. The browser reports what the policy would block without enforcing it, so you
tune against real traffic before anything breaks. For the full reporting workflow,
including what a violation report looks like, see
[Get started with CSP reporting](/en/blog/get-started-csp-reporting).

Once reports are arriving, [CentralCSP](/platform/csp-builder) collects them in one place,
groups the noise, and turns the raw payloads into something you can act on. You can
[start free](/register) and point your `Reporting-Endpoints` header at a CentralCSP
endpoint to see real reports within minutes.

<img alt="A setup check confirming the first browser reports arrived" src="__img0" width="1359" height="645" />

## Related [#related]

* [Get started with CSP reporting](/en/blog/get-started-csp-reporting)
* [CSP enforce vs report-only mode](/en/blog/csp-enforce-vs-report-only)

## Sources [#sources]

* [W3C, Reporting API](https://www.w3.org/TR/reporting-1/)
* [RFC 8941, Structured Field Values for HTTP](https://www.rfc-editor.org/rfc/rfc8941)
* [MDN, Reporting-Endpoints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Reporting-Endpoints)
