← Back to home

WebRTC IP vs header IP

A build of the pixel that keeps the production fire semantics — immediate fire on execution, SPA refire on history changes, bfcache refire — but replaces the payload. It never calls the wire API. Each fire asks the same question two ways: what IP does STUN report, and what IP does the HTTPS request itself carry? The second is what the collector resolves households from today.

No wire API traffic. No token is sent, no /wire or /wire/img request is made, and nothing is recorded server-side. All results stay in this tab.
Verdict
Waiting for the first fire…
The pixel fires as soon as the script executes.
A · WebRTC / STUN

RTCPeerConnection with a data channel, gathering ICE candidates against three public STUN servers. No getUserMedia, no permission prompt.

Server-reflexive IPv4 (srflx)
—
Server-reflexive IPv6
—
Status
idle
Candidates
0
Gather time
…
Host candidates: none exposed
The browser exposed no host candidates at all — the strongest form of the protection.
B · HTTP request headers

Plain CORS fetches. Each endpoint echoes the source IP of the request it received — the same value the wire collector reads off the socket for a pixel fire.

Observed IPv4
—
Observed IPv6
—
Sources OK
0 / 0
Distinct IPs
0
Slowest
…
waiting for first fire…
SPA navigation refires through the same debounced history hook the production pixel uses.
ICE candidates (0)
AddressTypeFamilyProtoNotet
No candidates gathered yet.
What changed vs the production pixel
  function firePixel() {
-   new Image().src = ENDPOINT
-     + '?token=' + TOKEN
-     + '&u=' + encodeURIComponent(location.href)
-     + '&t=' + (Date.now() + '_' + performance.now().toFixed(3));
+   probeWebrtc(run);   // RTCPeerConnection -> ICE candidates -> srflx IP
+   probeHeaders(run);  // CORS fetch -> source IP of the HTTPS request
  }

Full source: /wire-ip-probe.js. The SPA hooks, debounce and bfcache handler below firePixel() are unchanged from what staging serves for /wire.js.