SevyDevy

Guide · Frontend

Chrome's October 2026 Privacy Sandbox Removal Explained: What Ad Code Must Do

21 min readUpdated By Saket Bhatnagar

Researched and drafted with AI, reviewed and edited by Saket Bhatnagar.

In short

  • The privacy sandbox removal is Chrome taking out its ad APIs: Topics (interest labels from browsing), Protected Audience (ad auctions inside the browser) and fenced frames (sealed boxes for ads).
  • For Topics and Protected Audience, the real code is gone from Chrome 152 or 153 on. Fenced frames followed in Chrome 156. What remains is a stub, an empty stand-in that keeps the method name but does nothing useful. A simple 'is it there?' check still says yes, so ad code must also call it inside try and catch and treat an error or null as no data.
  • Key dates, as of 24 October 2026: Chrome is approved to delete the Topics stub names for all Stable users after 15 October. Stable is the version most people use. Protected Audience follows from 26 October. Chrome 157 reaches Stable on 3 November. Its fenced frame removal starts as a trial on the Canary and Beta test versions, and Stable users need a further approval.
  • The last step, deleting the stub names, rolls out through field trials: server-side switches that turn a change on for a share of users. Once a name is deleted, calling it throws TypeError. Some users still see the names, so code must handle both cases. Give ad slots a fixed size too, because a removed fenced frame collapses.
  • Beginners can stop after the ticket counter picture in the stub section. Engineers get what each API did in our Chromium 153 run, a tested helper that tells removed from present, and the layout trap when fenced frames disappear.

What goes wrong when Chrome removes the Privacy Sandbox ad APIs?

Ad code that still calls these APIs gets no useful data back, and how it fails depends on the user. Where Chrome still has the stubs, most calls fail quietly. Where the names are already deleted, the calls throw errors. The approved plans take that to all Stable users from late October 2026.

This is the privacy sandbox removal, and its main rollout steps land between 15 October and 3 November 2026. Code written as if the calls always succeed can stop at the first error or leave the ad slot empty.

Picture a common setup. A Hindi news site in Lucknow earns money from display ads, and its ad script runs four steps on every article page. The setup is made up, but each API call in it is real.

  • Ask Chrome for the reader's topics, such as "Sports" or "Travel", and send them to the ad server.
  • Add readers of cricket stories to an interest group, a named audience list stored in the browser, so a cricket-gear shop can reach them later.
  • Run an ad auction inside the browser that picks the best ad for this reader.
  • Show the winning ad inside a fenced frame, a frame the page cannot read into.

While the stubs are in place, step 1 answers with an error, steps 2 and 3 quietly do nothing, and step 4 has nothing to show. Once the names are deleted, steps 1 to 3 throw TypeError, the error JavaScript raises when you call something that is not a function. Either way, if the script did not catch the error on step 1, steps 2 to 4 never run. The fix has two parts: check that the name exists, then check that the call really returned data.

Which words do you need before reading about the Privacy Sandbox removal?

You need seven terms. Each one is explained in plain words here, then used through the rest of the guide.

  • Privacy Sandbox: a set of Chrome APIs, many of them meant to support ads without third-party cookies. Third-party cookies are cookies set by a site other than the one you are visiting.
  • Topics API: the document.browsingTopics() method. It returned a few broad interest labels that Chrome had worked out from your recent browsing.
  • Protected Audience: the joinAdInterestGroup() and runAdAuction() methods on navigator. They let a browser store audience lists and run an ad auction on the device. Chrome's own code and DevTools still call it Fledge.
  • Fenced frame: an element that works like an iframe but blocks data flow between the ad and the page around it. It existed to display auction winners.
  • Stub: a stand-in that keeps a method's name but does no real work. Calling it returns an error or an empty answer instead of crashing.
  • Field trial: a server-side switch that turns a code path on for a chosen share of Chrome users.
  • Milestone: a numbered Chrome release such as 156. Each one reaches Canary and Beta, early test versions, before the Stable channel, the version most people use. From Chrome 152 to 157, a new milestone reached Stable every two weeks.

What is the Privacy Sandbox removal, and when does it happen in 2026?

The privacy sandbox removal is Chrome deleting the ad-related Privacy Sandbox APIs in stages, with the main rollout steps between 15 October and 3 November 2026. First the settings were to be removed (planned for Chrome 150), then the real code was swapped for stubs. Now the stub names are being deleted for growing shares of users.

Google announced the retirement on 17 October 2025. Each API then got its own blink-dev thread, the public mailing list where Chrome engineers ask approval to ship or remove web features.

The Protected Audience and Topics threads both used the same four-step plan, posted on 11 June 2026. Step one, planned for Chrome 150, was to remove the ad settings through a field trial, after which calls in browsers in that trial would "always reject". Step two replaced the real code with a lightweight stub.

Steps three and four remove the stub through a field trial: first on Canary and Beta, then 1% of Stable. Full removal needs a fresh approval once 1% shows no breakage. The table shows where each API is.

Removal status as of 24 October 2026, from blink-dev (last messages: Topics 1 October, Protected Audience 30 September), Chrome Status and Chrome 156 release notes
API and its main namesWhat it didRemoval planDate to know
Topics: document.browsingTopics(), Sec-Browsing-Topics headerGave sites a few interest labels1% of Stable on 153+ with no breakage, held at 10% through 15 October, then 100%100% approved for after 15 October 2026
Protected Audience: joinAdInterestGroup(), runAdAuction()Stored audiences and ran ad auctions on the device10% of Stable through 12 October, then 100%100% rollout from 26 October 2026
Shared Storage and selectURL(): window.sharedStorageCross-site storage readable only in special scriptsIts interface was accidentally switched off from 153.0.8001.0; skipping the slow rollout was approved on 1 OctoberAlready missing in our Chromium 153 run
Fenced frames: the fencedframe element, window.fenceShowed auction winners in a sealed frameStubs in 156; element removal trial in 157 Canary and Beta, then 1% of StableChrome 156 Stable 20 October; Chrome 157 Stable 3 November 2026

How Topics and Protected Audience leave Chrome

Notice that the real code leaves early, in Chrome 152 or 153. The 1%, 10% and 100% steps only delete the stub names that were left behind. Fenced frames follow later: stubs in 156, then an element removal trial in 157.

Diagram connections:

  • Retirement announced to Deprecated in Chrome 144
  • Deprecated in Chrome 144 to Settings removed, 150
  • Settings removed, 150 to Code becomes a stub
  • Code becomes a stub to Names deleted for 1%
  • Names deleted for 1% to Names deleted for 10% (No breakage seen)
  • Names deleted for 10% to Names deleted for 100% (Approved 30 Sep to 1 Oct)
  • Retirement announced: 17 October 2025, Privacy Sandbox blog
  • Deprecated in Chrome 144: Planned in the November 2025 intents
  • Settings removed, 150: Field trial; calls planned to always reject
  • Code becomes a stub: Chrome 152 or 153: names stay, work stops
  • Names deleted for 1%: Field trial on Stable, watched for breakage
  • Names deleted for 10%: Held through 12 Oct or 15 Oct
  • Names deleted for 100%: Protected Audience from 26 October 2026

Why is Chrome removing Topics, Protected Audience and fenced frames?

Chrome is removing them because few sites used them once Chrome decided to keep third-party cookies. Google's 17 October 2025 post cites ecosystem feedback and "low levels of adoption" as the reasons.

The Topics and Protected Audience Chrome Status entries make the link to cookies plain. They say the APIs are going because Chrome will keep its current approach to third-party cookies. The APIs were built as a replacement for those cookies, so the case for them weakened.

Usage also fell over the year. The Topics thread reported calls on about 13% of page loads in November 2025, 4.9% in June 2026 and 2% in September 2026. The fenced frame thread reported the element on about 0.07% of page loads.

Those numbers count page loads where Chrome's use counters saw the API used. They do not count ads actually shown. Low use does not mean no breakage, as the next section shows.

What does a stub API do, and why does it fool feature detection?

A stub keeps the method's name but does no real work. So the classic check 'does this name exist?' passes, while the call itself fails or returns nothing. The fenced frame thread states this directly.

In that thread, the engineer who posted the removal intent explained why feature detection is not a reliable signal. The interface stays defined even when Privacy Sandbox is turned off, and the auction calls return null or reject.

Think of a closed railway ticket counter that still has its sign and window. You can queue and ask, and you either get a polite refusal or simply no ticket. The sign tells you nothing about whether tickets are sold.

Mapped to code, the sign is the method name, asking is the call, the refusal is a rejected promise and "no ticket" is a null result. Where the picture breaks: a closed counter turns everyone away the same way. The Topics stub rejects with a clear error, while the auction stub quietly returns null.

What we saw when we ran the APIs in Chromium 153

We launched Chrome for Testing 153.0.8010.12 through Playwright 1.63.0 on a localhost page on 24 October 2026. Playwright starts Chrome with field-trial config turned off, so this shows the build's own defaults, not what a Stable user with field trials sees.

Chromium 156 or newer was not available in our test setup. The behaviour of 156 and 157 below comes from Chrome's own release notes and Chrome Status, not from our run.

Run on Chrome for Testing 153.0.8010.12, Playwright 1.63.0, localhost page, 24 October 2026
CheckResult in our runWhat it means for your code
'browsingTopics' in documenttrueThe name exists, so this check alone is useless
await document.browsingTopics()Rejects with NotSupportedError: "document.browsingTopics() is deprecated and has been removed."An uncaught await stops the rest of your function
fetch(url, { browsingTopics: true })Request succeeds; no Sec-Browsing-Topics header reached our serverYour ad server stops receiving topics
navigator.joinAdInterestGroup(...)Resolves with nothing; DevTools Protocol commands for reading interest groups, such as Storage.getInterestGroupDetails, no longer existLooks like success but stores nothing you can inspect
navigator.runAdAuction(...)Resolves with nullSame answer as an auction nobody won
typeof window.sharedStorage"undefined"Shared Storage is already gone in this build
typeof HTMLFencedFrameElement"function"; the element measured 304 by 154 pixelsThe element still exists before Chrome 157
typeof window.fence"object", but the value is null on a normal pageNot a stub effect: window.fence was always null outside a fenced frame, and typeof null is 'object'. Test the value, not its type

Two more details showed up. Calling the APIs raised deprecation issues in DevTools, of types "Topics" and "Fledge". A Permissions-Policy header naming join-ad-interest-group or run-ad-auction now logs an "Unrecognized feature" warning in the console.

Secure context matters too. The Topics and Protected Audience methods only exist on secure pages, meaning HTTPS or localhost. On a plain data: URL those names were absent, and calling document.browsingTopics() threw TypeError: "document.browsingTopics is not a function". The fenced frame interface was still defined there.

Why do some Chrome users still have the APIs after 26 October 2026?

Some users still have the API names because the last step is a field trial, which reaches users in shares and can be paused or rolled back. A Stable user may be inside or outside the trial group, or may run an older Chrome.

One approval in the Topics thread was conditional on a progressive field-trial rollout, so breakage could be watched and the change rolled back. That matches the shape of both plans: 1%, then 10% for about two weeks, then 100%.

For a page, there are three kinds of Chrome visitor. The diagram walks through what document.browsingTopics() does for each one.

What a Topics call does for different Chrome users

Notice that no branch returns real topics on Chrome 153 or newer, and the June plan puts the stub in 152 as well. Only the shape of the failure differs. Older Chrome is not covered by our test, which is why the helper below can still report "available".

Diagram connections:

  • Ad script calls Topics to Chrome 153 or newer?
  • Chrome 153 or newer? to Old code path (No)
  • Chrome 153 or newer? to In the removal trial? (Yes)
  • In the removal trial? to Name deleted (Yes)
  • In the removal trial? to Stub answers (Not in trial yet)
  • Ad script calls Topics: document.browsingTopics()
  • Chrome 153 or newer?: All sources agree on the stub from 153
  • Old code path: From 150, a trial was planned to make calls reject
  • In the removal trial?: 1%, then 10%, then 100% of Stable
  • Name deleted: 'in' check false; calling throws TypeError
  • Stub answers: Name exists; call rejects NotSupportedError

Is the removal milestone 152 or 153?

Nobody from Chrome has settled it in public as of 24 October 2026, so treat any Chrome from 152 on as stubbed or name-free. Chrome's own pages disagree; here is who says what.

  • The 11 June 2026 plan in both threads put the stub in Chrome 152.
  • On 23 September, the Protected Audience thread reported no regressions on 1% of Stable, written as "M152+".
  • On 24 September, the Topics thread reported 1% of Stable, written as "M153+".
  • Both Chrome Status entries, last updated on 21 August 2026, list 153 as the removal milestone.
  • On 7 September a reader in the Protected Audience thread noticed the methods still existed in Chrome 152 Stable. They asked whether the date slipped, and the thread has no reply.

The methods still existing is not proof of a slip, because a stub keeps the names by design. Our 153 run shows the same names present with the work gone. For your code the answer is the same either way.

What breaks in Chrome 156 and Chrome 157 for fenced frames?

Chrome 156, Stable since 20 October 2026, turns the fenced frame element and the window.fence methods into stubs. No JavaScript call on them throws, and the window.fence reporting methods do nothing.

Chrome Status gives the reason this is safe. With Protected Audience and selectURL() removed, fenced frames can no longer be navigated, so they have nothing to show.

For Chrome 157, a field trial on Canary and Beta is planned to remove the stub element. Full removal on Stable needs another approval after 1% of Stable shows no breakage.

The layout trap when the element becomes unknown

Once the element is removed, the browser treats a fencedframe tag as an HTMLUnknownElement, its type for any tag it does not know. The fenced frame thread warns that it then loses its default 300 by 150 pixel size and collapses unless styled.

Our run shows the gap. In Chromium 153 a fenced frame measured 304 by 154 pixels. An unknown fakeframe tag measured 0 by 0, and a plain div holding only that tag collapsed to 0 height.

A div sized to 300 by 250 pixels in CSS kept that size with either tag inside. So size the slot's container, not the fenced frame. Better still, stop creating fenced frames at all, because there is no auction winner left to put in them.

How do you feature-detect the removed APIs safely?

Check that the name exists, then call it inside try and catch, and treat a rejection or a null result as "not available". The name check alone fails during the stub period, and the call alone throws once the name is deleted.

The helper below wraps the calls behind steps 1 to 3 of the news site's ad script. It runs both checks and falls back to contextual ads, meaning ads picked from the page's own content. You can paste it into the DevTools console on an HTTPS page to try it.

javascript
async function getTopicsSafely() {
  if (!('browsingTopics' in document)) {
    return { status: 'absent', topics: [] };
  }
  try {
    const topics = await document.browsingTopics();
    return { status: 'available', topics };
  } catch (err) {
    return { status: 'removed-or-blocked', topics: [], reason: err.name };
  }
}

async function joinGroupSafely(group, seconds) {
  if (typeof navigator.joinAdInterestGroup !== 'function') {
    return 'absent';
  }
  try {
    await navigator.joinAdInterestGroup(group, seconds);
    return 'called';
  } catch (err) {
    return 'failed';
  }
}

async function runAuctionOrNull(config) {
  if (typeof navigator.runAdAuction !== 'function') {
    return null;
  }
  try {
    return await navigator.runAdAuction(config);
  } catch (err) {
    return null;
  }
}

async function chooseAd() {
  const topics = await getTopicsSafely();
  const winner = await runAuctionOrNull({
    seller: location.origin,
    decisionLogicURL: location.origin + '/decide.js',
    interestGroupBuyers: [location.origin],
  });
  if (winner === null) {
    return { source: 'contextual', topicsStatus: topics.status };
  }
  return { source: 'auction', topicsStatus: topics.status };
}

To check it worked, run await chooseAd() in the DevTools console. In our Chromium 153 run on localhost it returned source "contextual" and topicsStatus "removed-or-blocked". joinGroupSafely() returned "called", because the stub resolves even though it stores nothing you can inspect.

We also simulated deleted names by removing the three methods from their prototypes before loading the helper. Then chooseAd() reported topicsStatus "absent" and joinGroupSafely() returned "absent", with no uncaught error.

Once the stub names are really deleted for your users, expect the same "absent" result on HTTPS pages. A result of "available" on Chrome 153 or newer would be a surprise worth logging and reporting.

What should ad code change before 3 November 2026?

Find every call, wrap or delete it, give ad slots a fixed size and remove dead headers. Treat 3 November, when Chrome 157 reaches Stable, as a practical target, not the day Stable removal is complete.

  1. Search your code and tags

    Look for browsingTopics, Sec-Browsing-Topics, joinAdInterestGroup, runAdAuction, fencedframe, window.fence, sharedStorage and selectURL. Include tag manager containers and inline scripts.

  2. Wrap what you cannot delete yet

    Use the helper pattern: a name check plus try and catch. Treat null from runAdAuction() as no ad, never as an error to retry.

  3. Delete what you own

    The real code is gone from Chrome 152 or 153 onward, so these calls cannot return useful data there. Removing them also removes the DevTools deprecation issues.

  4. Fix the ad slot layout

    Give each ad container an explicit width and height, and render fallback ads in a normal iframe instead of a fenced frame.

  5. Clean up headers and attributes

    Drop join-ad-interest-group and run-ad-auction from Permissions-Policy headers to stop console warnings. Handle the two Topics names in the next step.

  6. Decide on the opt-out headers

    The Topics plan also removes browsing-topics and interest-cohort, which 153 still recognised. Keep or drop them together: keeping browsing-topics=() still opts your site out on old Chrome versions with the real code. If Chrome stops recognising it, expect a console warning like the one join-ad-interest-group gave in our run. The browsingtopics attribute on iframe and img is ignored per the Topics plan.

  7. Ask your ad vendors

    If the calls come from a third-party ad script, ask which version stops calling these APIs and when it ships.

  8. Test on Chrome 156 and 157

    Load your pages in Chrome 156 Stable and Chrome 157 Beta and open the DevTools Issues panel. Your browser may be outside the trial, so check document.createElement('fencedframe').constructor.name first. HTMLFencedFrameElement means the stub is still there; HTMLUnknownElement means the element is removed.

  9. Simulate the removed element

    In the Elements panel, rename a fencedframe tag to an unknown name such as fakeframe. Confirm the ad slot keeps its size, whatever trial group your browser is in.

Which Privacy Sandbox APIs are not being removed?

CHIPS, FedCM and Private State Tokens stay, according to Google's 17 October 2025 post. CHIPS gives each top-level site its own copy of a third-party cookie. FedCM supports "sign in with" buttons, and Private State Tokens help fight fraud.

The same post also retires Attribution Reporting, Private Aggregation and Related Website Sets, plus the Android versions of several APIs. Those have their own removal threads and dates, which this guide does not cover.

In our Chromium 153 run, Attribution Reporting's attributionSrc and Related Website Sets' requestStorageAccessFor() were still present. Do not assume they share the Topics dates; check their own Chrome Status entries.

How do you explain the Privacy Sandbox removal in a system design interview?

Treat it as a question about building on a platform API that can disappear. Interviewers listen for how you handle a dependency you do not control.

  1. State the change in one line

    Chrome is removing Topics, Protected Audience and fenced frames in stages: code replaced by stubs, then names deleted through a field trial.

  2. Name the failure modes

    A call can reject, return null or not exist at all. An element can lose its default size. Each needs a separate check.

  3. Design for absence

    Wrap every optional browser API behind one module that returns a clear status. The rest of the ad code reads that status and falls back to contextual ads.

  4. Explain the rollout model

    Field trials reach 1%, then 10%, then 100% of users, and can be rolled back. Your code sees mixed behaviour during that window.

  5. Add observability

    Log the status each user gets, such as available, removed-or-blocked or absent, by Chrome version. That shows when it is safe to delete the fallback.

  6. Close with the trade-off

    Detection code costs little and protects revenue during the rollout. Deleting the calls entirely is cleaner once logs show no user gets real data.

Questions people ask

Is the Privacy Sandbox removal the same as Chrome blocking third-party cookies?
No, it is close to the opposite. The Chrome Status entries say the APIs are being removed because Chrome will keep its current approach to third-party cookies. The ad APIs were built to replace those cookies. With cookies staying, Google judged the APIs not worth keeping, given low adoption.
Will my site break if it still calls document.browsingTopics()?
It can, depending on how the call is written. On the stub, the promise rejects with NotSupportedError, so an await without try and catch stops the surrounding function. Once the name is deleted, the call throws TypeError at once, so a .then().catch() chain does not catch it. A name check plus try and catch handles both cases.
Is checking for HTMLFencedFrameElement a reliable test?
No. Chrome 156 keeps the element as a stub, so the interface still exists while nothing can be shown in it. The fenced frame thread itself says feature detection is not a reliable signal. It only tells you whether the element still exists, which is useful for testing layout, not whether an ad can be shown. Decide based on whether an auction returned a winner.
Why did Chrome use stubs instead of deleting the APIs at once?
For fenced frames, Chrome Status and the fenced frame thread give the reasons: no JavaScript call should throw, and an unknown element loses its default size. More generally, stubs let Chrome delete the real code first, then remove the names slowly through a field trial. One Topics approval required the rollout to be progressive, so breakage could be watched and the change rolled back.
Which Chrome version did this guide test, and what did it not test?
We ran Chrome for Testing 153.0.8010.12 through Playwright 1.63.0 on 24 October 2026, with field-trial config turned off. We did not have Chrome 156 or 157. Their fenced frame behaviour comes from the Chrome 156 release notes and Chrome Status, and the rollout dates come from blink-dev threads.
Is the Android Privacy Sandbox being removed too?
Yes, per the 17 October 2025 announcement. It lists the Android versions of Topics, Protected Audience and Attribution Reporting, plus Protected App Signals, SDK Runtime and On-Device Personalization, among the retired technologies. This guide covers only the Chrome web APIs and their dates.

Sources and further reading

Practise this with Lala

Practise