← Deprecate and remove: Private Aggregation API
v152 · privacy sandbox · reporting · sunset
Aggregatable reports pipeline
The reporting half of the removed Private Aggregation API: how worklet contributions became encrypted aggregatable reports, where the browser delivered them, and the server-side aggregation that turned them into summary reports — including the precise order in which each stage shut down.
Summary-report computation on the server side stopped operating in late December 2025, ahead of the client-side API surface (ChromeStatus feature notes). Former users were directed to debug reports as a bridge. Retained encrypted report payloads have no supported processing path.
the pipeline, end to end
- Contribute. Worklet code called
privateAggregation.contributeToHistogram(); contributions were validated (bucket < 2128, non-negative value) and queued for the invocation. - Assemble. When the worklet invocation ended, the browser packaged the contributions into an aggregatable report — a struct carrying the reporting origin, original report time and (randomized) report time, the contribution list, the API context (“shared-storage” or Protected Audience), a report ID, an aggregation coordinator, an optional context ID, and the filtering-ID byte bound (draft — §4.8 Aggregatable report).
- Encrypt. The contribution payload was encrypted to the aggregation service’s public key, fetched from
.well-known/aggregation-service/v1/public-keyson the coordinator’s origin; the browser could not read it back and neither could the reporting origin. - Deliver. The browser POSTed the report — JSON with a
shared_infoenvelope and anaggregation_service_payloadsarray — to a fixed path on the reporting origin:.well-known/private-aggregation/report-<api>(for examplereport-shared-storage). Reports could not be sent to arbitrary endpoints — only that well-known path (draft — report scheduling & serialization). - Aggregate. The origin later batched encrypted payloads to the aggregation service (a trusted-execution-environment deployment), which decrypted, summed with noise, and produced summary reports.
endpoint contract
| Report destination | https://<reporting origin>/.well-known/private-aggregation/report-<api> — fixed, per-API suffix; no arbitrary endpoints (draft) |
|---|---|
| Public keys | .well-known/aggregation-service/v1/public-keys on the aggregation coordinator’s origin |
| Method | Browser-initiated POST, on a delay, with retries per the browser’s reporting machinery; not interceptable by page script |
| Body | JSON object: shared_info (origin, times, report ID, API context) + aggregation_service_payloads (encrypted contribution ciphertext) |
| Now | Origins can stop serving the endpoint once disablement is complete for their traffic; the browser stops generating reports when the API is off |
sunset sequence
| Stage | State |
|---|---|
| Server-side summary-report computation | Ended late December 2025, ahead of everything else; affected users notified in advance and pointed at debug reports; “no user-facing breakage” by design (feature notes) |
| Client-side contribution (worklet calls) | Deprecated from Chrome 144; removal planned from Chrome 150 and filed at milestone 152; executed as staged Finch disablement (see the overview timeline) |
Report delivery (.well-known POSTs) | Stops automatically once no contributions are made; no endpoint changes are required of sites, but retained payloads are unprocessable |
| Debug reports | The sanctioned bridge for former server-side users; ends together with the API surface (feature notes) |
examples
The delivery step, as an origin’s .well-known endpoint would have seen it (field set per the draft’s aggregatable-report struct and serialization; ciphertext elided):
POST /.well-known/private-aggregation/report-shared-storage HTTP/1.1
Host: ad-tech.example
Content-Type: application/json
{
"shared_info": "{\"reporting_origin\":\"https://ad-tech.example\",
\"api\":\"shared-storage\", \"report_id\":\"<uuid>\", ...}",
"aggregation_service_payloads": [
{ "payload": "<encrypted contributions — opaque to the origin>" }
]
}
An aggregation-service batch later turned many such payloads into one summary report: per-bucket sums plus noise — the only output where individual user contributions were (probabilistically) protected. That service is what shut down in late December 2025.
Source: report struct and wire keys per the Private Aggregation API draft (§4.8, §9); shutdown per the ChromeStatus feature notesbrowser compatibility
The pipeline was Chromium-only end to end; no other engine generated or accepted these reports. Interim table (no BCD entry; webstatus.dev zero matches, 2026-07-29):
| Browser | Support | Evidence |
|---|---|---|
| Chrome | Generated reports until staged disablement (deprecated 144, removal filed 152) | milestone=152 listing; feature notes |
| Edge | Follows Chromium | Chromium-based; no separate position on record |
| Firefox | Never implemented | mozilla/standards-positions #805 |
| Safari | Never implemented | WebKit/standards-positions #189 |
security and privacy
- Encryption boundary: contribution payloads were readable only by the aggregation service’s TEE deployment; the reporting origin saw only
shared_infometadata (draft). - Fixed endpoint: the
.well-known-only delivery rule prevented the API from being repurposed as an arbitrary exfiltration channel. - After sunset: retained ciphertext is undecryptable through any supported path (server-side computation ended late December 2025) — origins holding payloads should treat them as inert and delete per their retention policy (feature notes).