← Declarative Performance Observer
v151 · origin trial · http header
Performance-Observer header
The HTTP response header that activates the Declarative Performance Observer: a structured-field-style dictionary naming a reporting endpoint, the built-in entry types to collect, an allowlist of user-timing marks/measures, and the early-failure opt-in. Honored only on the top-level main-document navigation response.
syntax
Performance-Observer: report-to="telemetry",
entry-types=("navigation" "mark" "visibility-state"),
include-user-timing=("hero-image-loaded" "next-link-clicked"),
capture-early-failures=?1
Reporting-Endpoints: telemetry="https://log.example.com/v1"
The header carries four directives. Reporting-Endpoints (defined by the Reporting API, not by this proposal) must accompany it to define the endpoint named by report-to.
Source: explainer — syntax.
report-to
| Value | A string naming an endpoint group defined in the same response's Reporting-Endpoints header (e.g. "telemetry") |
| Behavior | Routes the session report to the named endpoint; delivery uses the Reporting API (application/reports+json) |
| If the endpoint is undefined | Not specified in the explainer (2026-07-28). Related constraint: reporting endpoints are intentionally not persisted across navigations — Reporting API v1 is ephemeral and document-tied — so a report can only be sent while a document has supplied a valid endpoint |
Source: explainer — syntax; deferred reporting; Reporting API.
entry-types
| Value | A list of strings selecting built-in performance or visibility events to record (explainer examples: "navigation", "mark", "visibility-state") |
| Behavior | The browser process records the selected entry types for the session — independent of any page JavaScript |
| Allowed values | Values match PerformanceObserver.supportedEntryTypes per the explainer; it does not pin down the exact subset honored during the origin trial (2026-07-28) |
| Unknown values | Not specified in the explainer (2026-07-28) |
Source: explainer — syntax.
include-user-timing
| Value | A list of strings: an allowlist of user-defined performance.mark()/performance.measure() names to sync to the browser process (e.g. "hero-image-loaded") |
| Behavior | Marks/measures whose names appear in the allowlist are captured — including their detail payloads — even though they are created by page JavaScript |
| Third-party collision | Any script on the page (including third parties) can emit a mark with an allowlisted name and pollute telemetry; the explainer's mitigation is specific, non-generic mark names |
| Design alternative | Extending markOptions on performance.mark() was considered and rejected — any third-party script could set the option |
| Non-allowlisted / malformed names | Marks not in the allowlist are simply not synced (the allowlist defines the boundary); handling of a malformed list value is not specified in the explainer (2026-07-28) |
Source: explainer — syntax, telemetry pollution, considered alternatives.
capture-early-failures
| Value | Boolean (?1 to enable, ?0/false to disable; the explainer writes capture-early-failures=false for explicit opt-out) |
| Behavior when enabled | Persists an origin-level flag: the browser records subsequent early navigation failures (network errors before any response) as synthesized, zero-filled PerformanceNavigationTiming entries and stores them in a bounded on-disk buffer, flushed on the next successful navigation to the origin that supplies a reporting endpoint |
| Default / malformed | Off — nothing is persisted unless the origin opts in; handling of a malformed boolean is not specified in the explainer (2026-07-28) |
| Lifecycle | Flag and buffered reports expire after 7 days (Chromium); both are purged by Clear-Site-Data "storage" and by the user clearing site data; stored in partitioned storage, Incognito-isolated. Full lifecycle on the overview |
Source: explainer — deferred reporting and deactivation.
context and exposure
- Top-level main-document responses only. The header is honored on the primary navigation; iframe documents and subresource responses cannot activate observation for the main document — the feature is first-party by design.
- No JavaScript API. There is no script surface to detect or call; activation exists only as this header (plus the origin-trial token requirement during Chrome 151–155).
- Session scope. Observation lasts for the receiving document's session and deactivates when the report is dispatched; it does not outlive the document (the
capture-early-failures origin flag is the single exception).
- Full proposal. The header and its directives are defined by the Declarative Performance Observer explainer (pre-incubation; no standalone specification exists as of 2026-07-28).
Source: explainer — safe API design, deactivation.
examples
# Minimal: navigation + session-end only, one endpoint
Reporting-Endpoints: telemetry="https://log.example.com/v1"
Performance-Observer: report-to="telemetry", entry-types=("navigation")
# Full: early-failure capture and allowlisted app marks
Reporting-Endpoints: telemetry="https://log.example.com/v1"
Performance-Observer: report-to="telemetry",
entry-types=("navigation" "mark" "visibility-state"),
include-user-timing=("hero-image-loaded" "next-link-clicked"),
capture-early-failures=?1
Source: explainer — syntax.
browser compatibility
| Browser | Support |
| Chrome / Edge (Chromium) | Origin trial 151–155 (desktop, Android, WebView) — ChromeStatus / Intent to Experiment; no BCD entry |
| Firefox | No signal (no position recorded) |
| Safari | No signal (no position recorded) |
security & privacy
- Header-only activation prevents script-based telemetry hijacking; first-party/main-document-only scope.
- Reports are delivered only to endpoints the same response configured (Reporting API isolation); shared endpoints can correlate across origins.
- The
capture-early-failures flag and buffered reports are partitioned, 7-day-expiring, and cleared with site data — see the overview security section.
Source: explainer — security and privacy considerations.