| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| privacy:privacy_sandbox [2026/09/01 17:17] – Apply the generic review: Attribution Reporting DID have a CDP surface until April 2026, so the page's own headline gap is closable on a pinned build - new box, new table row, annotated listeners; add HTTP headers as a third observation surface with the f karel.kubicek.claude | privacy:privacy_sandbox [2026/09/01 17:36] (current) – Second review round: restore the eighth call to the probe output box and explain why it throws (a probe artefact, not API behaviour); drop the unsupported 'reporting origin' clause from the headers table; name the exact devtools-protocol commit that remov karel.kubicek.claude |
|---|
| * The same day, the UK CMA **closed** its Privacy Sandbox investigation and released Google from the commitments that had constrained the project since 2022. Case opened 2021-01-07, closed **2025-10-17**.(([[https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes|CMA case page, "Investigation into Google's 'Privacy Sandbox' browser changes"]]: "Case state: Closed", "Opened: 7 January 2021", "Closed: 17 October 2025". Fetched 2026-09-01.)) | * The same day, the UK CMA **closed** its Privacy Sandbox investigation and released Google from the commitments that had constrained the project since 2022. Case opened 2021-01-07, closed **2025-10-17**.(([[https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes|CMA case page, "Investigation into Google's 'Privacy Sandbox' browser changes"]]: "Case state: Closed", "Opened: 7 January 2021", "Closed: 17 October 2025". Fetched 2026-09-01.)) |
| * **They have not been removed yet.** As of **2026-09-01**, every one of those Chrome Platform Status "Deprecate and remove" entries is still marked //Proposed//, and Chromium **151.0.7922.34** exposes and answers every one of the APIs — measured on this page. Chrome stable today is **M152** (2026-08-25); this run had no M152 binary, so "not removed" in M152 rests on the //Proposed// flag and on M151, not on a probe. The removal milestone for Topics, Protected Audience, Attribution Reporting, Shared Storage, Related Website Sets and ''requestStorageAccessFor'' is **M153, whose stable date is 2026-09-08**. | * **They have not been removed yet.** As of **2026-09-01**, every one of those Chrome Platform Status "Deprecate and remove" entries is still marked //Proposed//, and Chromium **151.0.7922.34** exposes and answers every one of the APIs — measured on this page. Chrome stable today is **M152** (2026-08-25); this run had no M152 binary, so "not removed" in M152 rests on the //Proposed// flag and on M151, not on a probe. The removal milestone for Topics, Protected Audience, Attribution Reporting, Shared Storage, Related Website Sets and ''requestStorageAccessFor'' is **M153, whose stable date is 2026-09-08**. |
| * **The removal dates have already slipped twice.** The original blink-dev intent named M144 and then M150; the current entries say M152, M153 and M155, and none of them has shipped. Treat "days" as the optimistic reading and check the entry rather than this sentence. | * **Removal is a staircase, not a date, and it slipped.** Chrome's own blink-dev intent for Topics said "Deprecate in M144 and then remove in M150"; the API was duly deprecated in M144, the removal did not happen in M150, and the current entry says M153. Treat "days" as the optimistic reading and check the Chrome Platform Status entry rather than this sentence. |
| * **A code-removal milestone is the //latest// end of the window, not the only date.** Chrome ramps features down through server-side field trials before the code goes, so deployed behaviour can change without a milestone. We did not establish whether that is already happening to these specific APIs; a crawl run on an automation Chromium with no variations seed will not see it either way. | * **The behaviour changes before the code does, through field trials, and your crawler is exempt.** From **M150** Chrome removes the ads-API settings surfaces "via field trial", and — Chrome's own words — "after this point, all API invocations for field-trial enabled browsers will always reject". **M152** replaces the Topics implementation with "a lightweight stub API", rolled out through another field trial.((Yao Xia, blink-dev, "Intent to Deprecate and Remove: Topics API", thread opened 2025-11-07; the phased plan is in the message of 2026-06-12. [[https://groups.google.com/a/chromium.org/g/blink-dev/c/_R85yctz4Rs|groups.google.com/a/chromium.org/g/blink-dev/c/_R85yctz4Rs]], fetched 2026-09-01.)) A crawl driving an automation Chromium has **no variations seed**, so it is never in the field trial and will keep seeing the API work after real users have stopped seeing it. That is not a detail: it means the code-removal milestone is the //latest// possible end of the window for deployed behaviour, and your instrument systematically lags the population you are describing. |
| * So there is a window, it is short, and **the browser version is the single most important thing to pin and report** in any Privacy Sandbox measurement. See [[#What to Report]]. | * So there is a window, it is short, and **the browser version is the single most important thing to pin and report** in any Privacy Sandbox measurement. See [[#What to Report]]. |
| </WRAP> | </WRAP> |
| **Measured here, 2026-09-01, Chromium 151.0.7922.34 as shipped with Playwright 1.62.1.** Every Privacy Sandbox JS surface is present under the default flags of both Playwright and Puppeteer, and ''document.featurePolicy.allowsFeature()'' returns ''true'' for all six ads-API Permissions-Policy features (''browsing-topics'', ''join-ad-interest-group'', ''run-ad-auction'', ''attribution-reporting'', ''shared-storage'', ''private-aggregation''). Adding ''%%--enable-features=PrivacySandboxAdsAPIsOverride%%'' changed nothing, in either library. (Puppeteer was pointed at the same Chromium binary via ''chromium.executablePath()'', so this is a comparison of the two libraries' **default flag sets**, not of two browser builds.) | **Measured here, 2026-09-01, Chromium 151.0.7922.34 as shipped with Playwright 1.62.1.** Every Privacy Sandbox JS surface is present under the default flags of both Playwright and Puppeteer, and ''document.featurePolicy.allowsFeature()'' returns ''true'' for all six ads-API Permissions-Policy features (''browsing-topics'', ''join-ad-interest-group'', ''run-ad-auction'', ''attribution-reporting'', ''shared-storage'', ''private-aggregation''). Adding ''%%--enable-features=PrivacySandboxAdsAPIsOverride%%'' changed nothing, in either library. (Puppeteer was pointed at the same Chromium binary via ''chromium.executablePath()'', so this is a comparison of the two libraries' **default flag sets**, not of two browser builds.) |
| |
| That is the easy half. The hard half is that **calling them tells you nothing either**. On an HTTPS page served from a domain that is definitely not enrolled, every call returned a benign empty value rather than throwing: | That is the easy half. The hard half is that **calling them tells you nothing either**. On an HTTPS page served from a domain that is definitely not enrolled, seven of eight calls returned a benign empty value rather than throwing, and the eighth threw for a reason that has nothing to do with the Privacy Sandbox: |
| |
| <code> | <code> |
| navigator.runAdAuction() RETURNED null | navigator.runAdAuction() RETURNED null |
| sharedStorage.set() RETURNED undefined | sharedStorage.set() RETURNED undefined |
| | sharedStorage.worklet.addModule() OperationError: Rejecting load of https://…/w.js |
| | due to unexpected MIME type. |
| document.hasPrivateToken() RETURNED false | document.hasPrivateToken() RETURNED false |
| document.requestStorageAccess() RETURNED undefined | document.requestStorageAccess() RETURNED undefined |
| fetch(..., {attributionReporting}) RETURNED 200 | fetch(..., {attributionReporting}) RETURNED 200 |
| </code> | </code> |
| | |
| | The one error is an artefact of the probe, not of the API: that server returns ''text/html'' for every path, and a worklet module must be served as JavaScript. It is left in rather than trimmed out, because the trimmed version was on this page for one revision and a reviewer caught the difference between "no call threw" and "no call threw except the one I removed". |
| |
| The same four outputs came back from ''localhost'', from a mapped non-enrolled public-looking domain, with the ads-API override on, and with ''%%--privacy-sandbox-enrollment-overrides%%'' pointed at the origin. **A crawler cannot distinguish "the API is on and there was nothing to report" from "the API is off for this profile" from "this caller is not enrolled" by looking at the return value.** An empty Topics array is the expected result on a fresh profile with no history, and it is also what a disabled API gives you. | The same four outputs came back from ''localhost'', from a mapped non-enrolled public-looking domain, with the ads-API override on, and with ''%%--privacy-sandbox-enrollment-overrides%%'' pointed at the origin. **A crawler cannot distinguish "the API is on and there was nothing to report" from "the API is off for this profile" from "this caller is not enrolled" by looking at the return value.** An empty Topics array is the expected result on a fresh profile with no history, and it is also what a disabled API gives you. |
| |
| <WRAP important> | <WRAP important> |
| **Attribution Reporting already lost its CDP surface, and this is the most actionable thing on the page.** The ''Storage'' domain carried three ARA commands and four ARA events — ''setAttributionReportingTracking'', ''setAttributionReportingLocalTestingMode'', ''sendPendingAttributionReports'', and ''attributionReportingSourceRegistered'', ''attributionReportingTriggerRegistered'', ''attributionReportingReportSent'', ''attributionReportingVerboseDebugReportSent''. Bisecting the ''devtools-protocol'' repository on 2026-09-01: all seven are present in the descriptor as of **2026-04-01** and absent as of **2026-04-08**. Chromium 151 rejects the toggle with a protocol error, measured. | **Attribution Reporting already lost its CDP surface, and this is the most actionable thing on the page.** The ''Storage'' domain carried three ARA commands and four ARA events — ''setAttributionReportingTracking'', ''setAttributionReportingLocalTestingMode'', ''sendPendingAttributionReports'', and ''attributionReportingSourceRegistered'', ''attributionReportingTriggerRegistered'', ''attributionReportingReportSent'', ''attributionReportingVerboseDebugReportSent''. Bisecting the ''devtools-protocol'' repository on 2026-09-01: all seven are present at commit ''1abe750809'' (2026-03-25) and gone at ''96e032552f'' (2026-04-02, "Roll protocol to r1608973"), so they left the protocol on **2026-04-02**. Chromium 151 rejects the toggle with a protocol error, measured. |
| |
| So the corpus's biggest gap — nobody has measured a deployed Attribution Reporting API — is **still closable with first-class instrumentation, but only on an older binary**. M147 branched 2026-03-09 and reached stable 2026-04-07, so it should still carry the surface; M148 branched 2026-04-06, inside the removal window, so it is a coin flip. **That milestone mapping is inferred from branch points, not tested** — this run had only Chromium 151 available. Check the binary's own ''/json/protocol'' before you build on it, which takes one HTTP request: | So the corpus's biggest gap — nobody has measured a deployed Attribution Reporting API — is **still closable with first-class instrumentation, but only on an older binary**. M147 branched 2026-03-09 and reached stable 2026-04-07, so it should still carry the surface; M148 branched 2026-04-06, inside the removal window, so it is a coin flip. **That milestone mapping is inferred from branch points, not tested** — this run had only Chromium 151 available. Check the binary's own ''/json/protocol'' before you build on it, which takes one HTTP request: |
| ^ Header ^ Direction ^ What it tells you ^ | ^ Header ^ Direction ^ What it tells you ^ |
| | ''Attribution-Reporting-Eligible'' | request | The browser is willing to register a source or trigger on this request. Its presence marks the request as ARA-relevant | | | ''Attribution-Reporting-Eligible'' | request | The browser is willing to register a source or trigger on this request. Its presence marks the request as ARA-relevant | |
| | ''Attribution-Reporting-Register-Source'' | response | A source (an ad view or click) is being registered. The JSON value names the destination site and the reporting origin | | | ''Attribution-Reporting-Register-Source'' | response | A source (an ad view or click) is being registered. The JSON value names the ''destination'' site; the reporting origin is implicit — it is whichever origin sent the header | |
| | ''Attribution-Reporting-Register-Trigger'' | response | A conversion is being registered | | | ''Attribution-Reporting-Register-Trigger'' | response | A conversion is being registered | |
| | ''Sec-Browsing-Topics'' | request | The topics the browser is disclosing to this caller | | | ''Sec-Browsing-Topics'' | request | The topics the browser is disclosing to this caller | |
| |
| If you are looking for a gap to fill, **Attribution Reporting is measured by nobody**. Three papers in 5,869 name it — a related-work list, a browser-permissions census that counts how often sites //feature-detect// it, and one arXiv citation in a reference list. Not one instruments it, crawls for it, or reports its deployment prevalence. Given the M153 target, the window to measure a deployed Attribution Reporting API in Chrome is days — if M153 holds, and it has slipped twice. The instrument to use is not the current build: see the box in [[#Chrome DevTools Protocol: what it covers, and for how long]]. | If you are looking for a gap to fill, **Attribution Reporting is measured by nobody**. Three papers in 5,869 name it — a related-work list, a browser-permissions census that counts how often sites //feature-detect// it, and one arXiv citation in a reference list. Not one instruments it, crawls for it, or reports its deployment prevalence. Given the M153 target, the window to measure a deployed Attribution Reporting API in Chrome is days — if M153 holds, and it has slipped twice. The instrument to use is not the current build: see the box in [[#Chrome DevTools Protocol: what it covers, and for how long]]. |
| | |
| | ==== The only post-2025 adoption numbers that exist are Chrome's own ==== |
| | |
| | The corpus stops in February 2025 (see [[#Open Questions]]). Chrome publishes usage figures as its justification for removal, inside the Chrome Platform Status "Deprecate and remove" entries, and as of 2026-09-01 they are the only measurement of what happened after the April 2025 reversal. **They are vendor telemetry, unaudited, with no stated methodology, and the unit is usually //page loads// rather than //sites//** — so they are not comparable with anything in the table below without saying which unit you mean. Quoted because there is nothing else, not because they are good: |
| | |
| | ^ API ^ What Chrome's own removal entry says ^ |
| | | Topics | "currently at 13% of page loads" in the entry filed 2025-10-22; the blink-dev follow-up of 2026-06-12 says "Currently the usage is 4.9% of page loads" | |
| | | Shared Storage | "currently at ~11% of page loads" | |
| | | Protected Audience | "Use of the ''joinAdInterestGroup()'' API has decreased by almost 100x and use of the ''runAdAuction()'' API has decreased by more than 10x. Of the auctions occurring today, virtually none of them have winners" | |
| | | Related Website Sets | "currently at 71 sets", and ''requestStorageAccessFor'' "at about 0.95% of pageloads" | |
| | | Attribution Reporting | no usage figure given — the entry argues from "we expect adoption to decrease over time" | |
| | |
| | All fetched from ''chromestatus.com/api/v0/features/'' on 2026-09-01. Two things a reader should notice. **The RWS set count in the entry (71) is not the count in the list today (70)**, because the entry is a snapshot from late 2025 and the list has since been archived — a one-set discrepancy, but a good illustration of why you date an artefact. And **Chrome's Shared Storage figure of ~11% of page loads sits next to {[nisenoff2025_exploiting]}'s 10.1% of //sites//** from February 2025; the closeness is a coincidence of units, not a corroboration. |
| |
| ==== What the corpus did measure ==== | ==== What the corpus did measure ==== |
| | {[lin2024_browsing]} IMC 2024 | what blocking third-party cookies actually changes | Tranco top 10,000; 7,490 domains crawled successfully | More than **90%** of domains showed **less than a 10%** screenshot difference with third-party cookies disabled — the "cookieless web looks different" premise is largely not true at the page level | | | {[lin2024_browsing]} IMC 2024 | what blocking third-party cookies actually changes | Tranco top 10,000; 7,490 domains crawled successfully | More than **90%** of domains showed **less than a 10%** screenshot difference with third-party cookies disabled — the "cookieless web looks different" premise is largely not true at the page level | |
| |
| One adjacent paper gives the CHIPS context without measuring the attribute: {[bahrami2025_cookieguard]} (IMC 2025) describes CHIPS as "an opt-in model for cookie partitioning" and contrasts it with Firefox's Total Cookie Protection and Safari's ITP, which partition by default — which is why a CHIPS adoption figure is a measure of //publisher and tracker uptake//, not of browser policy. ({[kancherla2025_least]} is cited on this page only for its third-party storage-access figures on [[Privacy:Browser storage]]; it never discusses CHIPS, and an earlier draft wrongly attached this claim to it.) The only dedicated CHIPS adoption study we found is outside these seven venues: Zöllner, Feldmann and Dao, //A First Look at Cookies Having Independent Partitioned State//, PAM 2025.((''doi.org/10.1007/978-3-031-85960-1_8'', pages 182–196. Verified against Crossref 2026-09-01. Note that {[rasaii2025_crumbs]} cites this paper with a different and incorrect DOI; use the one here.)) We have not read it and quote no figure from it. | One adjacent paper gives the CHIPS context without measuring the attribute: {[bahrami2025_cookieguard]} (IMC 2025) describes CHIPS as "an opt-in model for cookie partitioning" and contrasts it with Firefox's Total Cookie Protection, "isolating all storage (including cookies) on a per-site basis", and Safari's ITP. (The paper does not use the word "default" of Firefox and Safari; that gloss is ours, and it is supported by [[Privacy:Browser storage]] rather than by this paper.) — which is why a CHIPS adoption figure is a measure of //publisher and tracker uptake//, not of browser policy. ({[kancherla2025_least]} is cited on this page only for its third-party storage-access figures on [[Privacy:Browser storage]]; it never discusses CHIPS, and an earlier draft wrongly attached this claim to it.) The only dedicated CHIPS adoption study we found is outside these seven venues: Zöllner, Feldmann and Dao, //A First Look at Cookies Having Independent Partitioned State//, PAM 2025.((''doi.org/10.1007/978-3-031-85960-1_8'', pages 182–196. Verified against Crossref 2026-09-01. Note that {[rasaii2025_crumbs]} cites this paper with a different and incorrect DOI; use the one here.)) We have not read it and quote no figure from it. |
| |
| ===== Denominators and Pitfalls ===== | ===== Denominators and Pitfalls ===== |
| <WRAP todo> | <WRAP todo> |
| * **Nobody has measured a deployed Attribution Reporting API.** Three passing mentions in 5,869 papers, no instrumentation, no prevalence. The removal target is M153. | * **Nobody has measured a deployed Attribution Reporting API.** Three passing mentions in 5,869 papers, no instrumentation, no prevalence. The removal target is M153. |
| * **Nobody has re-measured Protected Audience or Topics adoption after 2025-04-22.** {[calderonio2024_fledging]}'s crawl is from 2023 and {[nisenoff2025_exploiting]}'s from February 2025 — both before the retirement announcement. Chrome's own removal justification claims usage collapsed; no independent measurement of that collapse exists in this corpus. | * **Nobody independent has re-measured Protected Audience, Topics or Shared Storage adoption after February 2025.** {[calderonio2024_fledging]}'s crawl is from 2023 and {[nisenoff2025_exploiting]}'s from February 2025 — both before the retirement announcement. The only figures for the collapse are Chrome's own, quoted above; nobody has checked them, and the browser that produced them is the one being measured. |
| * **The RWS list has grown from 41 sets to 70** between {[mcquistin2024_first]}'s snapshot and today, and its repository is now archived. Nobody has published the end-state census or repeated the pull-request analysis on it. | * **The RWS list has grown from 41 sets to 70** between {[mcquistin2024_first]}'s snapshot and today, and its repository is now archived. Nobody has published the end-state census or repeated the pull-request analysis on it. |
| * **CHIPS adoption is measured once inside this corpus and once outside it**, both at around 1% of tracking cookies. CHIPS is one of the three APIs that survives; a proper longitudinal series on it is missing and now has a stable target to measure. | * **CHIPS adoption is measured once inside this corpus and once outside it**, both at around 1% of tracking cookies. CHIPS is one of the three APIs that survives; a proper longitudinal series on it is missing and now has a stable target to measure. |