Document Policy
Configure Document Policy reporting to enforce performance standards and detect when resources violate your policies for image sizes, script execution, and media dimensions.
New to Document Policy monitoring? Read our Document Policy overview to understand the benefits before diving into configuration.
What is Document Policy?
Document Policy is a WICG specification that provides a framework for enforcing performance constraints on web documents. Using HTTP headers, you define policies that control behaviors like image sizing, script execution, and resource loading — and browsers enforce these rules automatically.
Unlike Permissions Policy which controls access to powerful APIs (camera, microphone, geolocation), Document Policy
focuses on performance behaviors. It uses parametrized values (decimals, thresholds) rather than
simple boolean enable/disable. For example, you can set oversized-images=2.0 to allow images up to
2× their container size, while blocking anything larger.
Document Policy controls 10 performance behaviors: block document.write() and
synchronous XHR, enforce image compression ratios, require dimensions on media elements, restrict animations to
GPU-friendly properties, and more. When a resource violates your policy, the browser can block it and send a
violation report.
Specification
- WICG Document Policy — Official specification
- Document Policy Explainer — Technical overview with examples
- Can I Use: Document Policy — Browser support data
Browser Support
Document Policy has ~77% global browser support, covering Chromium-based browsers. Firefox and Safari do not support Document Policy.
| Browser | Support | Notes |
|---|---|---|
| Chrome | 85+ | Full support including reporting |
| Edge | 85+ | Full support including reporting |
| Opera | 71+ | Full support |
| Firefox | — | Not supported |
| Safari | — | Not supported |
Why Monitor Document Policy Violations?
Document Policy violations reveal important information about performance issues:
- Performance visibility — See every oversized image, blocking script, and resource violation. Know exactly what’s slowing down your pages.
- Proactive optimization — Catch performance regressions in staging before they reach production. Identify issues during CI/CD rather than through user complaints.
-
Third-party accountability — Track which vendor scripts violate your performance standards.
See which integrations use
document.write()or synchronous XHR. - Regression detection — Get alerted when new deployments introduce oversized assets or blocking behaviors that degrade Core Web Vitals.
- Compliance evidence — Document that performance policies are enforced. Prove to stakeholders that your performance budget is being maintained.
Who Benefits
- Performance engineers — Enforce performance budgets and identify optimization opportunities across the site
- DevOps teams — Integrate performance policy violations into CI/CD pipelines and deployment gates
- Frontend architects — Set performance standards that apply to all teams and third-party integrations
- Engineering leadership — Track performance governance metrics and demonstrate compliance with performance SLAs
When to Enable
Document Policy monitoring is recommended for:
- E-commerce sites — Where page speed directly impacts conversion rates and revenue
- High-traffic applications — Where performance regressions affect large numbers of users
- Mobile-first sites — Where bandwidth constraints make image optimization critical
- Sites with third-party scripts — Where vendor behavior needs to be monitored and governed
Start with Report-Only mode to understand your current violations before enforcing restrictions.
How to Configure
Step 1: Set Up the Reporting Endpoint
First, define where browsers should send violation reports using the Reporting-Endpoints header:
Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-ENDPOINT-UUID"
Replace YOUR-ENDPOINT-UUID with your application's unique endpoint from the
reporting-api.app dashboard.
Step 2: Enable Report-Only Mode for Testing
Before enforcing your policy, test it using Document-Policy-Report-Only. This sends violation reports
without blocking any resources, letting you see what would fail:
Document-Policy-Report-Only: oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default" Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-UUID"
This configuration would report (but not block) any image exceeding 2× its container size, any parser-blocking
script, or any use of document.write().
Document-Policy-Report-Only before enforcing policies. Your site may have legitimate
cases where policies are violated. Report-Only mode reveals these without breaking functionality.
Step 3: Configure Policy Directives
Define which behaviors to control. Document Policy supports two types of directives:
Boolean Directives
Set to ?0 to disable a behavior:
Document-Policy-Report-Only: sync-script=?0, sync-xhr=?0, document-write=?0, *;report-to="default"
This blocks parser-blocking scripts, synchronous XHR, and document.write().
Decimal Directives
Set a threshold value:
Document-Policy-Report-Only: oversized-images=2.0, lossy-images-max-bpp=0.5, *;report-to="default"
This policy:
oversized-images=2.0— Allow images up to 2× their container sizelossy-images-max-bpp=0.5— Require lossy images to be under 0.5 bytes per pixel
Step 4: Monitor Reports and Identify Violations
After deploying Report-Only mode, monitor incoming reports in your dashboard. Look for:
- Image violations — Oversized or poorly compressed images that need optimization
-
Script violations — Parser-blocking scripts that should use
asyncordefer -
Third-party violations — Vendor scripts using deprecated patterns like
document.write()
For each violation, decide whether to:
- Fix the resource — Optimize the image, update the script
- Adjust the threshold — Loosen the policy if the limit is too strict
- Accept and block — The behavior is unacceptable; proceed with enforcement
Step 5: Switch to Enforcement
Once you've resolved all issues, switch from Report-Only to enforced mode:
Document-Policy: oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default" Reporting-Endpoints: default="https://reporting-api.app/browser-reports/YOUR-UUID"
Remove the -Report-Only suffix to start blocking violating resources. Keep
*;report-to="default" to continue receiving reports about blocked resources.
Step 6: Set Up Integrations
Route Document Policy violation reports to your existing tools:
- AppSignal integration — Track violations alongside application errors
- Webhook integration — Send reports to performance monitoring systems
- Google Chat integration — Post alerts to team chat spaces
See the Integrations documentation for setup instructions.
Understanding Violation Reports
When a resource violates your Document Policy, browsers send JSON reports to your endpoint. These reports identify exactly which policy was violated and where.
Report Fields
| Field | Description |
|---|---|
policyId |
The policy directive that was violated (e.g., oversized-images, sync-script)
|
disposition |
enforce if blocked, report if Report-Only mode
|
message |
Human-readable description of the violation |
sourceFile |
URL of the resource that violated the policy |
lineNumber |
Line number where the violation occurred (for scripts) |
columnNumber |
Column number where the violation occurred |
Example Report
{
"type": "document-policy-violation",
"age": 23,
"url": "https://example.com/products/widget",
"body": {
"policyId": "oversized-images",
"disposition": "enforce",
"message": "Image is 4x larger than its container",
"sourceFile": "https://cdn.example.com/images/hero-banner.jpg"
}
}
This report shows a hero banner image that's 4× larger than its container, violating the
oversized-images policy. The disposition: "enforce" indicates the image was blocked
(replaced with a placeholder).
Interpreting Disposition
-
report— Report-Only mode. The resource was allowed but logged. Use this for testing. -
enforce— Enforcement mode. The resource was blocked. Users see a placeholder or broken resource.
Common Policy Directives
Document Policy supports 10 directives grouped into two categories: boolean (enable/disable) and decimal (threshold-based).
Boolean Directives
Set to ?0 to disable these behaviors:
| Directive | Controls | Performance Impact |
|---|---|---|
sync-script |
Parser-blocking scripts | High — blocks render until script loads/executes |
sync-xhr |
Synchronous XMLHttpRequest | High — blocks main thread during request |
document-write |
document.write() API |
High — blocks parser, can break page on slow connections |
unsized-media |
Media without explicit dimensions | Medium — causes layout shift (CLS) |
layout-animations |
Non-GPU animations | Medium — forces layout recalculation |
font-display-late-swap |
Late font swapping | Medium — causes layout shift when fonts load |
Image Optimization Directives
Set decimal thresholds to enforce image quality standards:
| Directive | Controls | Recommended |
|---|---|---|
oversized-images |
Max downscaling ratio (intrinsic vs rendered size) | 2.0 or lower |
lossy-images-max-bpp |
Bytes per pixel for lossy images (1KB overhead) | 0.5 (0.2 for WebP) |
lossless-images-max-bpp |
Bytes per pixel for lossless images (10KB overhead) | 1.0 (0.5 for WebP) |
lossless-images-strict-max-bpp |
Strict lossless check (1KB overhead) | 0.5 |
Recommended Thresholds
Based on web.dev guidance and Web Performance Calendar recommendations:
Document-Policy-Report-Only: oversized-images=2.0, lossy-images-max-bpp=0.5, lossless-images-max-bpp=1.0, sync-script=?0, sync-xhr=?0, document-write=?0, unsized-media=?0, *;report-to="default"
oversized-images=3.0) and tighten them as you optimize your assets. This
prevents blocking legitimate content while you improve.
Directive Syntax
Document Policy uses Structured Headers syntax. Here's how to format your policies:
| Syntax | Meaning | Example |
|---|---|---|
directive=?0 |
Boolean false (disable) | sync-script=?0 |
directive=?1 |
Boolean true (enable, default) | sync-script=?1 |
directive=N.N |
Decimal threshold | oversized-images=2.0 |
*;report-to="name" |
Report all violations to endpoint | *;report-to="default" |
Multiple directives are combined with commas:
Document-Policy: oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"
*;report-to="default" parameter must come at the end of your policy and applies to all directives.
The * is a wildcard meaning “for all policies.”
Server Configuration Examples
Nginx
server {
# ... your existing configuration ...
# Reporting endpoint
add_header Reporting-Endpoints 'default="https://reporting-api.app/browser-reports/YOUR-UUID"' always;
# Document Policy with reporting (Report-Only for testing)
add_header Document-Policy-Report-Only 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"' always;
# Or enforced mode:
# add_header Document-Policy 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"' always;
}
Ruby on Rails
# Add Document Policy headers with reporting # Note: Use lowercase header names for Rack 3 compatibility config.action_dispatch.default_headers.merge!( "reporting-endpoints" => 'default="https://reporting-api.app/browser-reports/YOUR-UUID"', # Report-Only for testing: "document-policy-report-only" => 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"' # Or enforced mode: # "document-policy" => 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"' )
Apache
Header always set Reporting-Endpoints 'default="https://reporting-api.app/browser-reports/YOUR-UUID"' # Report-Only for testing: Header always set Document-Policy-Report-Only 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"' # Or enforced mode: # Header always set Document-Policy 'oversized-images=2.0, sync-script=?0, document-write=?0, *;report-to="default"'
Troubleshooting
Reports Not Appearing
- Check browser support — Document Policy reporting only works in Chromium-based browsers (Chrome 85+, Edge 85+). Firefox and Safari do not support this feature.
-
Verify headers are sent — Use browser DevTools (Network tab) to confirm both
Document-Policy(orDocument-Policy-Report-Only) andReporting-Endpointsheaders are present. -
Check
report-toparameter — The policy must include*;report-to="default"to send reports. - Trigger a violation — Ensure a resource is actually violating your policy. Try loading an obviously oversized image to test.
Resources Still Loading Despite Policy
-
Check Report-Only vs Enforce —
Document-Policy-Report-Onlysends reports but doesn't block. Switch toDocument-Policyto enforce. -
Verify threshold values — Ensure your thresholds are actually being exceeded. An
oversized-images=4.0policy won't block a 3× oversized image. - Check header parsing — Malformed headers may be silently ignored. Use browser DevTools to check for parsing errors.
Policy Syntax Errors
-
Use correct boolean syntax — Boolean values use
?0and?1, nottrue/false - Decimal values need a decimal point — Use
2.0, not2 -
Wildcard report-to at end —
*;report-to="default"must come after all other directives
Next Steps
- Integrations — Route reports to your observability tools
- Permissions Policy — Control sensitive API access
- Getting Started — Set up your first application