---
title: "Collect reports of blocked content · Agent Wranglers"
url: https://agentwranglers.se/playbook/application-security/browser-security-headers/reporting-endpoints
id: APS-26
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1124
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Collect reports of blocked content

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Browser security headers](https://agentwranglers.se/playbook/application-security/browser-security-headers.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: APS-26
- Level: Recommended
- Chapter: [Browser security headers](https://agentwranglers.se/playbook/application-security/browser-security-headers.md)
- Rule: Name a place for browsers to send policy errors with `Reporting-Endpoints`. Log those reports without any personal data.
- Check: Break the policy on a test page in two browsers. Each report appears in the log as one line with a path and a directive. A 1 MB POST answers 413.
- How: Send `Reporting-Endpoints: csp-endpoint="/reports"` and point `report-to csp-endpoint` at it. Also add `report-uri /reports` for browsers without `report-to`. Those send one `application/csp-report` object instead of a list. Accept both types, cap the body at 64 KB and put the endpoint behind the [rate limit](https://agentwranglers.se/playbook/application-security/limits-and-business-logic/rate-limits.md). Log only the type, path and directive, never the full address or the visitor's IP address. Alert on spikes as [Log attacks without personal data](https://agentwranglers.se/playbook/application-security/errors-logs-and-vulnerabilities/security-logging.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### HTTP example

```http
Reporting-Endpoints: csp-endpoint="/reports"
Content-Security-Policy: default-src 'self'; report-to csp-endpoint; report-uri /reports
```

### JavaScript example

```js
// Express: accepts application/reports+json (a list) and application/csp-report (one object)
app.post('/reports', express.json({ type: ['application/reports+json', 'application/csp-report'], limit: '64kb' }), (req, res) => {
  const reports = Array.isArray(req.body) ? req.body : [{ type: 'csp-violation', url: req.body['csp-report']?.['document-uri'], body: { effectiveDirective: req.body['csp-report']?.['effective-directive'] } }];
  for (const r of reports) console.log(r.type, URL.parse(r.url ?? '')?.pathname, r.body?.effectiveDirective);
  res.status(204).end();
});
```

### Python example

```python
# Flask: same two formats, body capped by MAX_CONTENT_LENGTH
from urllib.parse import urlsplit
app.config["MAX_CONTENT_LENGTH"] = 64 * 1024

@app.post("/reports")
def reports():
    data = request.get_json(force=True, silent=True) or []
    if isinstance(data, dict):
        old = data.get("csp-report", {})
        data = [{"type": "csp-violation", "url": old.get("document-uri", ""), "body": {"effectiveDirective": old.get("effective-directive")}}]
    for report in data:
        print(report.get("type"), urlsplit(report.get("url", "")).path, report.get("body", {}).get("effectiveDirective"))
    return "", 204
```

## Sources

- [W3C Reporting API](https://www.w3.org/TR/reporting-1/)
- [CSP Level 3 (the report-to directive)](https://www.w3.org/TR/CSP3/#directive-report-to)

## Related rules

- APS-49 [Limit how often anyone can call your APIs](https://agentwranglers.se/playbook/application-security/limits-and-business-logic/rate-limits.md) in Application security
- APS-80 [Log attacks without personal data](https://agentwranglers.se/playbook/application-security/errors-logs-and-vulnerabilities/security-logging.md) in Application security

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/application-security/browser-security-headers/reporting-endpoints">Agent Wranglers application security playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Allow only the scripts you wrote](https://agentwranglers.se/playbook/application-security/browser-security-headers/content-security-policy.md)
- Next: [Stop browsers guessing file types](https://agentwranglers.se/playbook/application-security/browser-security-headers/x-content-type-options.md)
- [Browser security headers](https://agentwranglers.se/playbook/application-security/browser-security-headers.md)
