Skip to main content
Magnet link structure diagram showing xt hash parameter and tr tracker parameters that the extension removes

Trackerless Magnets Browser Extension: Notes

Magnet links typically contain both a hash identifying the content and one or more tracker URLs. The trackers are not required for torrent clients that support DHT (Distributed Hash Table) and PEX (Peer Exchange) — they are fallback mechanisms from the tracker-dependent era of BitTorrent, before DHT enabled fully decentralised peer discovery. Leaving tracker URLs in magnet links passed to a torrent client announces your IP address to those specific tracker servers, which may log it. A browser extension that strips tr= parameters from magnet links before handing them to the torrent client removes that tracker contact without affecting the torrent client's ability to find peers through DHT. This page covers why trackers in magnets are technically optional, the WebExtensions API approach to intercepting magnet link navigation, and the implementation considerations. These notes are part of the developer notes. For browser extension context broadly, see the browser extensions topic hub. The privacy rationale connects to the privacy and security topic hub.


Why trackers in magnets are optional

→ Short Answer

A magnet link's essential component is the xt (exact topic) parameter — a URN containing the infohash that uniquely identifies the torrent. The tr (tracker) parameters are hints for torrent clients that haven't found peers through other means. A client with DHT enabled announces to the DHT network using the infohash and discovers peers without contacting any tracker. Trackers in magnet links are a convenience for DHT-disabled clients and legacy trackers — they're not part of the content identifier.

The privacy issue is that clicking a magnet link with tracker URLs causes the torrent client to immediately announce to each listed tracker, revealing the user's IP address and what infohash they're downloading. Trackers log these announcements. A magnet link from a site could include a tracker that the site operator controls, giving them visibility into when and from where their links are used — even if users never revisit the site.

Removing tr= parameters leaves the torrent client to find peers exclusively through DHT and PEX. For active, well-seeded torrents this works at least as well as tracker-based discovery. For obscure or very new torrents with minimal DHT presence, removing trackers can slow initial peer discovery.


Extension architecture

The extension needs to intercept magnet link navigations before the browser hands the magnet: URI to the registered protocol handler (the torrent client). There are two approaches in the WebExtensions API: intercepting via tabs.update after detecting the magnet link in page content, or intercepting via declarativeNetRequest / webRequest rules.

⚙ Compatibility Note

The webRequest API can observe navigations to non-HTTP schemes in some browsers but handling is inconsistent. Chrome and Firefox handle magnet: protocol navigation differently — in Chrome, clicking a magnet link fires a navigation event that the extension can observe; in Firefox, the protocol handler may be invoked before the extension can intercept. The most reliable cross-browser approach uses a content script to intercept magnet link click events directly in the page, modify the href before the default action fires, and then programmatically trigger the modified magnet URI.

Content script — intercept and strip magnet link trackers
// content_script.js
document.addEventListener('click', function(e) {
const target = e.target.closest('a[href^="magnet:"]');
if (!target) return;

const original = target.href;
const url = new URL(original);

// Remove all 'tr' (tracker) parameters:
const params = new URLSearchParams(url.search);
const cleaned = new URLSearchParams();
for (const [key, value] of params) {
if (key !== 'tr') {
cleaned.append(key, value);
}
}

// Reconstruct without trackers:
const cleanedMagnet = 'magnet:?' + cleaned.toString();

if (cleanedMagnet !== original) {
e.preventDefault();
window.location.href = cleanedMagnet;
}
}, true); // capture phase to run before page handlers
⬡ Observed Behaviour

The content script approach works reliably for standard magnet link anchor elements. It does not handle magnet links opened programmatically by JavaScript (via window.location.assign or window.open) unless those calls are proxied. The vast majority of magnet links on public sites use standard anchor elements, so the content script covers the practical use case. Sites that open magnet links via JavaScript are uncommon and typically do so for UX reasons (click tracking, confirmation dialogs) that the extension would bypass anyway.


Manifest and permissions

manifest.json — minimal permissions for content script approach
{
"manifest_version": 3,
"name": "Trackerless Magnets",
"version": "1.0",
"permissions": [],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content_script.js"],
"run_at": "document_idle"
}
]
}

The content script approach requires no special permissions beyond content script injection, which Manifest V3 handles through content_scripts declaration. No webRequest, tabs, or host_permissions are needed, which keeps the extension's privilege surface minimal. The <all_urls> match pattern injects the script on all pages — a more targeted match pattern (e.g., specific torrent index sites) is possible but limits coverage.

↻ What Changed

Manifest V3 removed synchronous webRequest blocking in Chrome, which was the original approach used by extensions that needed to modify requests before they fired. For magnet link manipulation, this doesn't matter much — the content script approach was always more appropriate than request interception for a URI scheme that doesn't go through normal HTTP request infrastructure. The MV3 transition did not significantly complicate this specific extension type.


Edge cases and limitations

⚠ Common Pitfall

The URL parsing approach using new URL() on a magnet URI works in modern browsers but the resulting URL object has non-standard behaviour: the pathname is empty, all parameters land in the search string, and the search string starts with ? rather than the technically correct magnet URI format. When reconstructing the cleaned magnet URI, using 'magnet:?' + cleaned.toString() rather than modifying url.search and calling url.toString() produces a more reliable output that torrent clients parse correctly.

Some magnet links encode tracker URLs that are themselves encoded — tr=https%3A%2F%2Ftracker.example.com%2Fannounce — and some use multiple tr parameters in a single magnet URI. The URLSearchParams getAll('tr') approach handles both cases correctly, while a regex-based replacement might not strip all trackers if the encoding is unexpected.


When this is and isn't useful

This kind of extension is useful for users who run DHT-capable torrent clients and want to avoid broadcasting infohash lookups to tracker operators. It's not a comprehensive privacy tool — DHT itself involves announcing to distributed nodes — but it removes the specific tracker-based disclosure that magnet link trackers introduce.

For users running torrent clients with DHT disabled, stripping trackers degrades peer discovery. The extension should detect or allow DHT status as a configuration option if targeting a general audience rather than assuming DHT availability.