# Configure per-document features with Document-Policy (/en/blog/document-policy-explained)





The `Document-Policy` header lets you switch document-level features and constraints on or off for a single page, for example turning off `document.write`, requiring images to declare their dimensions, or blocking synchronous XHR. The browser enforces the constraint, and if you ask it to, sends a `document-policy-violation` report when the page crosses one. This post covers what the header configures, the report-only variant for measuring before you enforce, and how the violation reports reach you through the [Reporting API](/en/blog/how-to-set-up-the-reporting-api).

<Callout type="warn" title="Limited availability">
  Document-Policy is a WICG Community Group draft, not a finished W3C standard. Only Chromium-based browsers implement it; Firefox and Safari do not implement Document-Policy at all. Even in Chromium most configuration points are experimental. Treat the lists below as Chromium-specific and confirm a point is actually usable before you rely on it.
</Callout>

## What Document-Policy configures [#what-document-policy-configures]

The header is a list of configuration points, each one governing a single behavior of the document. A point takes a typed value: a boolean (`?0` for off, `?1` for on), an integer, a float, or an enum. Which points exist is decided by the browser, not a fixed registry, so the practical move is to set the ones you care about explicitly and watch the reports.

Which points you can rely on depends entirely on the browser. In Chromium, two are usable in normal browsing:

* `js-profiling` enables the JS Self-Profiling API, letting a page sample its own JavaScript so you can profile real-user performance in production.
* `include-js-call-stacks-in-crash-reports=?1` enriches a [browser crash report](/en/blog/browser-crash-reports) with a JavaScript call stack, so a crash points you at the code that caused it.

Several other points are defined in the draft but experimental. They exist only in Chromium and only take effect behind the `chrome://flags/#enable-experimental-web-platform-features` flag, so you cannot depend on them for real users yet:

* `document-write=?0` turns off `document.write`, a script-injection and rendering hazard that blocks the parser.
* `unsized-media=?0` requires media elements to declare a size, which prevents the layout shift an unsized image causes.
* `oversized-images` caps how far an image's intrinsic size may exceed its displayed size, so a page cannot ship a multi-megabyte image scaled down in CSS.
* `sync-xhr=?0` blocks synchronous `XMLHttpRequest`, which freezes the main thread.

A minimal example, using the experimental `document-write` point to show the header syntax:

```http
Document-Policy: document-write=?0
```

For the full, source-backed treatment of how the header parses and what each point means, see the [Document-Policy reference](/en/docs/web-security/policies/document-policy).

## The report-only variant [#the-report-only-variant]

`Document-Policy-Report-Only` evaluates the same constraints and reports what would break, without actually enforcing anything. That matters here more than for most headers, because the set of configuration points is implementation-defined: you want to confirm what actually fires in your users' browsers before you block it.

Run it the same way you would the enforcing header, but point each constrained point at a reporting endpoint. First declare the endpoint with [`Reporting-Endpoints`](/en/docs/web-security/reporting-api/headers/reporting-endpoints):

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

Then set the report-only policy and route the point at that endpoint:

```http
Document-Policy-Report-Only: document-write=?0;report-to=doc-endpoint
```

Each point can carry its own `report-to` parameter. A leading `*;report-to=endpoint` sets a default endpoint for every point, and `report-to=none` disables reporting for a specific one. Once the report stream goes quiet for a constraint, you can move it from the report-only header to the enforcing `Document-Policy` header.

## The document-policy-violation report [#the-document-policy-violation-report]

When the page does something a constraint forbids, the browser sends a `document-policy-violation` report to the endpoint you named. It tells you which point was violated and where, so you can find the code behind it.

```json
{
  "type": "document-policy-violation",
  "age": 420,
  "url": "https://example.com/",
  "user_agent": "Mozilla/5.0 ...",
  "body": {
    "policyId": "document-write",
    "disposition": "report",
    "message": "Document policy violation: document-write is not allowed.",
    "sourceFile": "https://example.com/script.js",
    "lineNumber": 11,
    "columnNumber": 12
  }
}
```

The `policyId` names the configuration point, `disposition` is `report` in report-only mode and `enforce` once you enforce, and `sourceFile` with the line and column points straight at the offending code. One gotcha to plan for: the report received at your endpoint names the field `policyId`, but the in-browser ReportingObserver JS interface exposes the same value as `featureId`, so expect the JS-API name to differ from the wire field. The full payload and field reference is on the [document-policy-violation report page](/en/docs/web-security/reporting-api/reports/document-policy-violation).

## Collect the reports without a backend [#collect-the-reports-without-a-backend]

A `document-policy-violation` report uses the same delivery path as your other browser reports, so it arrives in the same stream as your CSP, NEL, and crash reports. Point the `report-to` endpoint at [CentralCSP](/platform/csp-builder) and the document-policy reports land next to the rest, charted and searchable, instead of needing a separate pipeline for an experimental feature. That is also where the report-only signal becomes useful: you can size what a constraint would break across real traffic before you enforce it.

<img alt="Document Policy violations grouped by feature, with document-write and unsized-media rows and their dispositions" src="__img0" width="1359" height="434" />

## Next steps [#next-steps]

* Set up reporting end to end first: [how to set up the Reporting API](/en/blog/how-to-set-up-the-reporting-api).
* Read the [Document-Policy reference](/en/docs/web-security/policies/document-policy) and the [document-policy-violation report](/en/docs/web-security/reporting-api/reports/document-policy-violation).
* See how the call-stack point feeds [browser crash reports](/en/blog/browser-crash-reports).
* Declare your endpoint with the [Reporting-Endpoints header](/en/docs/web-security/reporting-api/headers/reporting-endpoints).

[Collect Document-Policy reports from real browsers](/register).

## Sources [#sources]

* [MDN, Document-Policy header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Document-Policy)
* [WICG, Document Policy specification](https://wicg.github.io/document-policy/)

## Related [#related]

* [What is NEL, network error logging from the browser](/en/blog/what-is-nel-network-error-logging)
* [Browser crash and unresponsive reports](/en/blog/browser-crash-reports)
* [How to set up the Reporting API](/en/blog/how-to-set-up-the-reporting-api)
