What a Swap Site Can Actually See: Fingerprints, DNS Leaks, WebRTC (2026 Tests)
We measured the three layers a swap site can score: a browser sent 14 headers and 636 bytes where curl sent 80, eight Chrome connections produced eight different JA3 hashes, a spoofed user agent was contradicted by its own client hints, SOCKS leaked four DNS packets (zero when resolved at the exit), and one STUN URL returned the real IP in three seconds.
A swap site is not recognising you; it is scoring one connection. Every judgement it can make comes from three layers. The network layer gives it your IP, its ASN and that address's history. The transport layer gives it your TLS ClientHello, which your browser writes before a single byte of HTML exists. The application layer gives it request headers, JavaScript-readable device fields and your behaviour over time. We measured all three today against our own listener and against veilswap.io. The gap between what people think they reveal and what is actually observable is large, and it is not in the direction most guides claim.
Network layer: your IP arrives with a résumé. Cloudflare's own documentation states that its bot score draws on IP reputation, request characteristics and TLS fingerprints, and the site sits behind Cloudflare, so that scoring happens before our code runs. This morning the host we measured from, a data-centre address at 64.118.134.27, fetched /exchange three times with three different user agents — curl/8.5.0, a Windows Chrome 141 string, and a HeadlessChrome 151 string. All three returned 200, all three returned 43,014 bytes, none contained a challenge marker. A data-centre IP is not, by itself, a rejection criterion here. What the origin does record is the CF-Connecting-IP header, and what it enforces is a rate: six orders per hour per IP, 120 globally per hour, and a 90-second duplicate window keyed on IP, corridor, amount and payout address.
DNS leakage is the cheapest mistake available. At 06:02 UTC we flushed the local resolver cache and fetched veilswap.io through Tor's SOCKS port with plain `--socks5`. A packet capture on the loopback interface recorded four UDP port-53 packets: two queries from 127.0.0.1 to the local stub at 127.0.0.53, two answers back. The request completed in 5.95 seconds. Repeating it with `--socks5-hostname`, which hands the hostname to the exit node instead of resolving it locally, produced zero DNS packets and finished in 2.75 seconds. Same URL, same exit, same tool. One leak is invisible in the page, invisible in the browser, and visible to whoever runs your resolver — which, on a home connection, is usually your ISP. (Is Tor safe for swaps?)
Transport layer: the ClientHello is more honest than the user agent. We ran a listener that records raw ClientHello bytes on a local TLS port. Chromium 151 offered TLS 1.3, 16 cipher suites and 17 extensions; across eight separate connections the cipher order was byte-for-byte identical, and the extension set was identical once sorted. Yet all eight produced different JA3 hashes, because Chromium randomises extension order on purpose. curl built on OpenSSL offered 31 cipher suites and 11 extensions, and two connections gave the same hash twice, 77f696ec… So a JA3 comparison is a weak signal in both directions: Chrome looks like a new client every time it connects, and a stable client looks suspiciously stable.
Spoofing the user agent makes the picture worse, not better. We relaunched the same browser with a Windows Chrome 141 user agent, en-US locale and America/New_York timezone. The user agent changed. Three neighbours did not: `navigator.userAgentData.brands` still read "Chromium/151" and "Not=A?Brand/99", `navigator.platform` still read "Linux x86_64", and the `sec-ch-ua` request header still said 151 while `sec-ch-ua-platform` had been rewritten to "Windows". A genuine Windows Chrome 141 sends a coherent set; a spoofed one sends a contradiction that no real browser produces. If the goal is to look ordinary, a UA switcher is the one tool that reliably makes you look unusual.
What the page can still read without any library. On the same machine, two runs returned: platform Linux x86_64, languages en-US and en, hardwareConcurrency 4, deviceMemory 4, maxTouchPoints 0, vendor Google Inc., a 1280×720 screen at 24-bit depth with devicePixelRatio 1, timezone UTC, and a WebGL renderer string naming ANGLE with a SwiftShader software device. Of twelve font names probed by width measurement, six were present: Arial, Courier New, Times New Roman, DejaVu Sans, Liberation Sans and Noto Color Emoji. Four cores, 4 GB of reported memory, 720p and a software rasteriser is the shape of a cloud container, not a laptop. One field did fail honestly: our canvas hash threw inside the headless context, so we have no value to report rather than a fabricated one.
WebRTC turns one line of JavaScript into your real address. With no STUN server configured, Chromium 151 returned a single host candidate obfuscated as a `.local` mDNS name — the local interface address stayed hidden. Adding one `stun:stun.l.google.com:19302` entry returned a server-reflexive candidate of 64.118.134.27 within three seconds, which is this machine's real public address, while the HTTP request itself went out through a SOCKS proxy. That is the mechanism people underestimate: WebRTC runs on UDP and does not consult the proxy settings. A proxy hides your HTTP path, not your network path. Tor Browser ships with WebRTC disabled for exactly this reason. (Is Tor safe for swaps?)
What the site itself did not collect. The /exchange response set zero cookies and sent no Content-Security-Policy; it does send a strict-origin referrer policy, nosniff, SAMEORIGIN framing and a permissions policy that disables camera, microphone and geolocation outright. The HTML is 43,014 bytes with 31 script tags, 18 of them Next.js chunks. But two third parties sit in that markup: an inline Microsoft Clarity loader for project yyim3c5trv with ref=bwt, and a preloaded ustat.js from a spst2.com subdomain. Both see your IP, your user agent and your click path directly, without touching our logs. Clarity is session replay, and `data-clarity-mask` appears exactly once in the page. "We keep no logs" and "this visit was not recorded" are different sentences.
Eight habits that do the work for the other side. (1) Changing only the user agent, which creates the contradiction above. (2) Changing IP without changing timezone or language. (3) Using `--socks5` instead of `--socks5-hostname`, which leaks DNS — four packets versus zero, measured. (4) Leaving WebRTC enabled behind a proxy, which hands over the real address in three seconds. (5) Ordering from your everyday browser profile, complete with extensions, fonts and replay scripts. (6) Creating the order over Tor and paying from clearnet, which welds two paths onto one deposit address. (7) Reusing one payout address for many orders; upstream deposit addresses are sometimes reused too, and we counted two addresses used four and seven times. (8) Bookmarking an order URL, which is a bearer capability, not a reference. (Is Tor safe for swaps?)
The order that actually holds up, and the boundary of these numbers. A separate browser container, Tor Browser with its default WebRTC block and remote SOCKS resolution, one fresh payout address per order, and the order link kept only for the minutes it is needed. We deliberately did not test how any particular exchange scores these signals: that model is private, and writing a guess would be fabrication. What is verifiable is narrow and enough — four DNS packets versus zero, eight connections producing eight JA3 hashes, a spoofed user agent contradicted by its own client hints, a STUN server returning the real address in three seconds. As of writing (2026-11-01, around 06:05 UTC) the site quoted 100 USDT-TRC20 as 0.14544658 XMR, about 687.54 USDT per XMR; 1,000 as 1.633163 and 5,000 as 8.167982, both near 612; and 1 XMR as 599.32 USDT across two routes at a 196 bps advantage. The catalogue showed 430 assets across 62 networks, with 53 stablecoins and 6 assets needing a tag. Rates move by the second; the live quote on the page is the one that counts. (Is Tor safe for swaps?)