Blog/March 4, 2026ยท10 min read

ISP Header Injection Explained: Supercookies, X-UIDH, and How to Detect Them

Some ISPs have injected hidden tracking identifiers into every HTTP request you make โ€” invisible to you, readable by advertisers. Here's how it works, when HTTPS stops it, what can still happen, and how to verify it yourself.

TL;DR

Real-World Cases of ISP Header Injection

It has happened at scale, documented by regulators and researchers.

Verizon Wireless: X-UIDH (2012-2016)
Verizon silently added an X-UIDH header to every HTTP request on their network. It contained a unique tracking ID tied to the account. Third-party advertisers could read it to track users across sites regardless of private browsing or cookie deletion. The FCC investigated; Verizon settled in 2016 and was required to obtain opt-in consent before using it.
AT&T GigaPower: Internet Preferences (2015)
AT&T's fiber service included a program called "Internet Preferences" that monitored browsing activity to serve targeted ads. Customers could opt out, for an extra $29/month. The default was surveillance. AT&T discontinued it under public pressure in 2016.
CarrierIQ (2011)
Software pre-installed by carriers on millions of handsets logged keystrokes, URLs, and SMS content and reported it back to the carrier. Discovered by security researcher Trevor Eckhart. The resulting lawsuits led to its removal.
Hotel and airport captive portals (ongoing)
Many hospitality networks inject JavaScript into unencrypted HTTP pages to display login screens or ads. This is functionally identical to ISP header injection: a middlebox modifying traffic in transit.
DNS NXDOMAIN hijacking (widespread)
Many ISPs redirect failed DNS lookups (non-existent domains) to their own search/ad pages instead of returning a proper NXDOMAIN error. Comcast, Spectrum, CenturyLink, and others have all done this. It breaks software that relies on NXDOMAIN and monetises your typos.

The Network Path: Where Injection Happens

To understand header injection you need to understand the network path of an HTTP request. There are several points between your browser and a destination server where a middlebox can read and modify the request.

HTTP request path (unencrypted)
[Your Browser]
  GET / HTTP/1.1
  Host: example.com
  User-Agent: Chrome/121
        |
        | (your home network)
        |
[ISP Router / Edge Node]
        |
        | โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
        | โ”ƒ ISP middlebox adds: โ”ƒ
        | โ”ƒ  X-UIDH: A1B2C3D4 โ”ƒ  โ† you never see this
        | โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
        |
[Destination Server]
  receives:
  GET / HTTP/1.1
  Host: example.com
  User-Agent: Chrome/121
  X-UIDH: A1B2C3D4   โ† injected header

The browser sent 3 headers. The server received 4. The browser has no way to observe this. It never sees what headers the server actually received.

Why HTTPS Mostly Prevents This

When you visit an HTTPS site, the connection is encrypted using TLS. The ISP can see the destination hostname (via SNI in the TLS handshake) but cannot read or modify the request headers or body; they're encrypted inside the TLS tunnel.

This is why Verizon's UIDH injection and most historical cases targeted HTTP traffic. As HTTPS adoption grew (it reached ~95% of browser traffic by 2023), mass header injection became largely infeasible.

There are exceptions though:

  • TLS-terminating middleboxes: A proxy that has a certificate your device trusts can terminate TLS, inspect and modify the decrypted request, then re-encrypt it toward the destination. The browser shows a padlock. The connection was intercepted. Corporate DLP appliances, some hotel networks, and documented ISP deployments do this.
  • Remaining HTTP traffic: Not all traffic is HTTPS. APIs, IoT devices, and legacy applications still make unencrypted requests.
  • CONNECT proxy tunnels: HTTP CONNECT proxies can read the plaintext before the TLS layer, depending on how the proxy is configured.

The Detection Technique: Server-Side Echo

The cleanest way to see what your ISP is adding is to run a server-side echo: send a request from the browser, have a server capture the exact headers it received, and send them back. The diff between what the browser sent and what the server received is what your ISP injected.

This is exactly what our test does. The /api/echo endpoint is a Next.js route deployed on Vercel. When your browser hits it, the server captures all incoming headers, strips known infrastructure headers (Vercel adds around 15 of its own), and returns the remainder as JSON. Your browser then checks that JSON against a list of known ISP tracking headers.

echo endpoint โ€” simplified
// Strip all Vercel/CDN infrastructure headers
const STRIP_PREFIXES = ['x-vercel-', 'x-amz-', 'cf-'];
const STRIP_EXACT = new Set([
  'host', 'accept', 'accept-encoding', 'accept-language',
  'x-forwarded-for', 'x-forwarded-proto', 'forwarded', ...
]);

// Whatever remains is what your ISP added
const filtered = {};
for (const [key, value] of request.headers) {
  if (!shouldStrip(key)) filtered[key] = value;
}
return Response.json({ receivedHeaders: filtered });

The tricky part is the strip list. Vercel adds headers like x-vercel-ip-country, x-vercel-ja4-digest, x-matched-path, and around a dozen others. If you don't strip these, every user would appear to have "proxy headers", which is exactly the false positive that triggered complaints at launch. The fix is prefix-based stripping rather than enumerating every header name, since Vercel adds new ones regularly.

Header Tampering: Did a Proxy Rewrite Your Request?

Header injection (ISP adds new headers) is one problem. Header modification is another: a proxy in the path rewrites headers your browser sent. This is a strong indicator of a man-in-the-middle device: a corporate DPI appliance, a transparent proxy, or ISP-operated traffic management equipment.

We detect this by capturing User-Agent and Accept-Language server-side and comparing them to navigator.userAgent and navigator.languages on the client. If the base language tag changed (e.g. en-US became en) or the User-Agent string was normalised, a proxy rewrote it. This is a genuine real-world signal: Blue Coat proxies, Squid, and some enterprise DLP tools are known to modify these headers.

WebRTC and the IP Exposure Problem

WebRTC is the browser API that powers video calls, peer-to-peer file sharing, and similar features. It works by discovering your public IP address via STUN (Session Traversal Utilities for NAT) servers (a standard protocol for punching through firewalls).

The problem: any website can initiate a WebRTC peer connection and collect your IP address as part of the ICE candidate discovery process. This happens over a side channel, not through a normal HTTP request, so it bypasses proxies and in many configurations it bypasses VPN tunnels too.

For a regular user on a home ISP this is mostly informational; the IP is already visible via HTTP. For VPN users it is a genuine leak: the VPN hides the connection IP, but WebRTC can reveal the real ISP-assigned IP to any website, defeating the anonymity the VPN was supposed to provide.

WebRTC IP collection โ€” browser-side
const pc = new RTCPeerConnection({
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    { urls: 'stun:stun.cloudflare.com:3478' },
  ],
});
pc.createDataChannel('');
pc.onicecandidate = (event) => {
  const ip = /(d{1,3}.){3}d{1,3}/.exec(
    event.candidate?.candidate ?? ''
  )?.[0];
  // Filter out RFC-1918 private ranges (192.168.x, 10.x, 172.16-31.x)
  // Whatever remains is a public IP
};
await pc.setLocalDescription(await pc.createOffer());

To mitigate: in Firefox, set media.peerconnection.enabled to false in about:config. In Chrome or Edge, uBlock Origin has a "Prevent WebRTC from leaking local IP addresses" option. Most VPN clients also have a WebRTC leak prevention setting.

What We Can't Detect (and Why)

Being honest about limitations matters. Here is what this type of browser-based test genuinely cannot do:

  • DNS resolver identification
    A browser cannot query which DNS server handled a given lookup. The only reliable way to test is with a dedicated DNS server you control: make a unique lookup, check if it arrived at your server, and from which resolver. We can't do this in a browser. We tell you if your connection IP belongs to a known VPN or privacy network, but that's not the same as knowing your DNS resolver.
  • HTTPS traffic inspection
    If your ISP is performing TLS inspection, the connection is terminated and re-encrypted before it reaches our server. We use indirect signals (Cloudflare WARP detection, Cloudflare trace anomalies) but these are not definitive. A sophisticated middlebox with a trusted CA certificate would be very hard to detect without client-side certificate pinning.
  • Deep packet inspection
    DPI at the ISP level happens below the TCP layer in some cases. Traffic shaping and protocol classification can be done without injecting headers โ€” there is no way to detect this from a browser.
  • Historical data
    We can only test what is happening right now on this connection. Your ISP's behaviour may vary by network segment, time of day, or traffic type.

False Positives: When It's Not Your ISP

This is important. Our tool (and any header echo tool) will show headers that look suspicious but are completely benign. Here are the main sources of false positives:

Corporate proxy / enterprise network
Many workplaces route all traffic through a proxy. It adds headers like Via, X-Forwarded-For, or custom identifiers. This looks identical to ISP injection, but it's your employer's network, not your ISP.
VPN exit nodes
Some VPN providers add Via or X-Forwarded-For to your requests as they exit through their servers.
Captive portals (hotels, airports)
Network login pages work by intercepting HTTP traffic. Headers will look modified until you authenticate.
CDN and reverse proxy headers
Cloudflare, Fastly, and similar CDNs add X-Forwarded-For and other headers to requests passing through them. Our server strips these โ€” but misconfigured setups can leak them back.
Vercel infrastructure (our own platform)
When deployed on Vercel, around 15 x-vercel-* headers are added to every inbound request. We strip all of them by prefix before echoing. If we didn't, every test would show false header injection.

How to Verify This Yourself

You don't need our tool. You can run the same check with curl. Point it at any server you control (or use a public echo service) and inspect the headers it received:

terminal
# See exactly what headers a server receives from you
curl -v https://httpbin.org/headers 2>&1 | grep "^>"

# Or use a verbose request to see both sent and received
curl -v https://httpbin.org/headers

# httpbin /headers returns a JSON of every request header
# it received โ€” compare to what your browser shows in
# DevTools โ†’ Network โ†’ any request โ†’ Request Headers

You can also check in browser DevTools: open Network tab, make any request, click it, and look at "Request Headers". These are the headers your browser sent. Compare that to what a server echo endpoint returns โ€” any difference was added in transit.

For a more thorough check, run the same curl request from your home network and from a mobile hotspot. Different injection behaviour on different networks is a strong signal.

The score is a weighted sum starting at 100. Each check applies a penalty or bonus:

SignalScore change
Known tracking header found (UIDH, X-ACT, etc.)โˆ’35
Header modified in transit (proxy tampering)โˆ’25
No VPN / WARP / self-attested DoHโˆ’20
VPN/WARP IP detected, or user confirmed DoH+8 to +9
TLS interception signalโˆ’40
WebRTC bypass while on VPNโˆ’15
ISP with documented surveillance history (AT&T, Verizon)โˆ’10
ISP with documented practices (Comcast, Spectrum, Cox)โˆ’8
Clean echo โ€” no suspicious headers+2

Scores are clamped to 0โ€“100. A score of 75+ is Low risk, 45โ€“74 is Medium, below 45 is High.

Try It

The full test runs in your browser in about 5 seconds. No sign-up, no install. Your IP is hashed with a daily-rotating salt before storage โ€” we cannot reverse it.

โ† All postsISP Leaderboard โ†’