A bounce-tracking detector
Why it matters Partitioning splits storage by the site in the address bar. A bounce tracker gets around that by briefly becoming the site in the address bar: a link sends you through it for a split second, it saves an ID in its own cookie, and it passes you on. You never see it, yet it recognises you every time. Engines answer by reading your history for this pattern and clearing the tracker's storage. You will write that detector.
Imagine a toll booth on a road you never meant to take. Every time a shortcut sends you through it, the attendant stamps your hand with the same number. You never stop there, never buy anything, never even notice it, but it has a record of every trip.
Redirect: a server's answer that says "go to this other address instead" (status 302 and a Location header). The browser follows it at once.
Hop: one stop on a chain of redirects. Clicking https://hop.example/r?to=https://shopb.example/ makes hop.example a hop and shopb.example the landing site.
Bounce tracker: a site that appears in your history only as a hop, saves storage while you pass through, and is never a site you actually use.
User interaction: a sign that you really used a site: you clicked, typed or scrolled on it as the page in front of you.
What engines do today
All three engines have some defence, with different reach (checked October 2026): Safari's Intelligent Tracking Prevention has handled bounce tracking since 2018; Firefox purges listed trackers daily by default since 2020 and runs full Bounce Tracking Protection in Strict mode; Chrome has a bounce-tracking defence since October 2023, but only for people who block third-party cookies. The lesson "Bounce tracking and its defences" compared them. The core idea is the same everywhere, and that is what you build.
The rule your detector uses
A site is flagged as a bounce tracker when both are true:
- It wrote storage while you were bouncing through it, in at least one navigation of the history.
- You have not interacted with it as a landing site in the last
window_daysdays. "In the last 45 days" includes a visit exactly 45 days ago:today - day <= window_days.
Flagged sites get their cookies and storage cleared. Next time they bounce you, they see a stranger.
The history
make_history(seed=0) runs the practice browser for 60 pretend days and returns (browser, history). The browser still holds every cookie it collected. history is a list of dicts, one per page Sam opened:
{"day": 12,
"hops": [{"site": "hop.example", "wrote_storage": True}],
"landed": "shopb.example",
"interacted": True}A list of dicts inside a dict looks busy, but you read it one layer at a time: visit["hops"] is a list, so loop over it; each hop is a dict, so ask for hop["site"].
for visit in history[:3]: # the first three navigations
for hop in visit["hops"]: # a list inside each visit, often empty
print(visit["day"], hop["site"], hop["wrote_storage"])Traps in the history, on purpose
go.exampleis a link shortener. It redirects but saves nothing, so it is not a bounce tracker.login.exampleis a sign-in service. It saves a cookie while bouncing you back to a shop, but Sam also opens it directly and signs in every few days. That interaction keeps it safe.oldsso.exampleis an old sign-in service Sam last used directly on day 2. On day 59 that is 57 days ago, outside a 45-day window, so the rule flags it. The cost is small and honest: next time Sam uses it, he signs in again.relay.examplewas the landing site once, but Sam did nothing there. Landing is not interacting.
Real engines are tuned around exactly these cases: catch the toll booths, spare the sign-in services people use.
Clearing storage
The practice browser has browser.clear_cookies(site) and browser.clear_storage(site), like the "clear data for this site" button in your browser's settings. browser.cookies(site) lists what is left.
Try it In your own browser, open Settings and search for "site data". The page it finds lists every site that has stored something on your device. Look for names you do not recognise: you may find a few redirect services you only ever passed through.
In other languages
The same detector in JavaScript, with a Set:
function findBounceTrackers(history, today, windowDays = 45) {
const bounced = new Set(), used = new Set();
for (const visit of history) {
for (const hop of visit.hops) {
if (hop.wrote_storage) bounced.add(hop.site);
}
if (visit.interacted && today - visit.day <= windowDays) used.add(visit.landed);
}
return new Set([...bounced].filter(site => !used.has(site)));
}And in Go, where a map[string]bool plays the part of a set:
bounced, used := map[string]bool{}, map[string]bool{}
for _, v := range history {
for _, h := range v.Hops {
if h.WroteStorage { bounced[h.Site] = true }
}
if v.Interacted && today-v.Day <= windowDays { used[v.Landed] = true }
}Recap
- Bounce trackers dodge partitioning by being the top-level site for a split second.
- Detect them from history: they write storage while bouncing you and you never really use them.
- Recent interaction is what separates a sign-in service from a toll booth.
- The defence is to clear the flagged site's storage, so the next bounce sees a stranger.
Write find_bounce_trackers(history, today, window_days=45). It returns a set of sites that wrote storage as a hop at least once (any visit, any day) and that Sam did not interact with as a landing site within the window (today - visit["day"] <= window_days with visit["interacted"] True). Write purge(browser, flagged), which calls browser.clear_cookies(site) and browser.clear_storage(site) for every flagged site and returns how many sites it purged. Then run browser, history = make_history(seed=0), set flagged = find_bounce_trackers(history, TODAY) and call purge(browser, flagged).
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.