UDP, Proxies, and the WebRTC Leak
The proxy carries the UDP. The browser refuses to hand WebRTC over. We tested every combination to find where your IP actually leaks.
More and more of the web runs on UDP now. HTTP/3 runs over QUIC, QUIC runs over UDP, and a good chunk of the sites we scrape already answer this way. Proxy providers noticed, and some of them started adding UDP support, since that’s the only way a UDP protocol can pass through a proxy at all. We wanted to understand what this actually gives us as scrapers, because UDP reaches a browser in two very different ways, and a proxy treats them differently.
For your scraping needs, having a reliable proxy provider like Decodo on your side improves the chances of success.
The first is the UDP we want, HTTP/3 for our requests. The second is the UDP we never asked for, the WebRTC traffic that a browser generates on its own, which can leak around the proxy and expose our real IP. But supporting UDP and actually getting a client to route its UDP through the proxy are two different problems, and the result changes a lot depending on the client. An HTTP client, a browser doing HTTP/3, and a browser doing WebRTC all behave differently, so we tested all three, end to end, to see where a UDP proxy does the work for us and where we still have to step in on the client side.
A quick recap of HTTP/2 and HTTP/3
We already covered the request side of HTTP/3 in Faster Web Scraping with HTTP/3, so let’s just recap what matters for proxies. HTTP/1.1 and HTTP/2 run on TCP. HTTP/3 drops TCP completely and runs on QUIC, which is built on UDP and merges the transport and TLS handshakes into one. The part that matters for us is the transport: a proxy built to relay TCP has nothing to grab onto in a QUIC connection, since there’s no TCP stream to relay.
Adoption is real, but it’s easy to overstate. If we look at traffic, HTTP/3 is around a fifth of all requests, while HTTP/2 is still the majority at almost half, and this split has stayed roughly the same through 2026 (Cloudflare Radar). If we look at site support instead, the number goes up: around 38% of sites advertise HTTP/3 via Alt-Svc (W3Techs). Italy, where our test machine sits, is one of the higher HTTP/3 markets at about 30%. So HTTP/3 is a serious, well-supported protocol, not some niche thing, but it hasn’t replaced HTTP/2 yet, and most real traffic is still on TCP.
HTTP/3 and QUIC run on UDP, so the proxy layer has to carry it too. anyIP gives compatible clients production-ready SOCKS5 UDP ASSOCIATE across its residential and mobile network.
The sales pitch follows naturally from here. If real browsers increasingly speak HTTP/3 and our scraper can’t, that difference becomes a signal, so we’d want to speak HTTP/3 too, and to do that through a proxy, the proxy has to carry UDP.
This is exactly what some providers are now selling. They offer UDP support, usually as a beta over SOCKS5, and they pitch it as a stealth feature: the idea is that most residential traffic is QUIC these days, so a client stuck on TCP stands out. There are two parts of this claim worth checking before relying on it, the stealth side and the tooling side, so we tested both, using a provider that carries UDP and one that doesn’t.
UDP support and the stealth question
Switching to HTTP/3 doesn’t remove protocol fingerprinting, it just moves it somewhere else. Detection happens at three layers, and moving from TCP to QUIC affects each one in a different way.
The TCP/IP stack fingerprint, meaning the SYN options, window sizes and TTL that give away the OS, really does disappear, because there’s no TCP handshake anymore. That’s the only layer that goes away, though. The TLS fingerprint stays exactly as it was, because QUIC still does a TLS 1.3 handshake, just wrapped inside QUIC instead of running over TCP. The ClientHello with its cipher suites and extensions is still there, and JA4 was designed to fingerprint the QUIC variant on purpose (Scrapfly QUIC/HTTP3 fingerprint). The HTTP/2 fingerprint, the SETTINGS frames, window updates and pseudo-header order, doesn’t get erased either. It just gets replaced by an HTTP/3 fingerprint built from QUIC transport parameters.
And those QUIC transport parameters are basically the same thing we were trying to get away from. Scrapfly says it clearly: they “work like HTTP/2 SETTINGS frames but at the transport layer.” Values like max_udp_payload_size and initial_max_data, and the order they come in, are different between Chrome’s quiche, Firefox, Go’s quic-go and ngtcp2, and that difference is itself a fingerprint (Scrapfly HTTP/2 and HTTP/3 fingerprinting). QUIC even adds new signals that have no TCP equivalent at all, like 0-RTT behavior and connection migration support.
So the layer that actually gets scrapers blocked today is TLS and HTTP/2 fingerprinting, which Cloudflare, Akamai and DataDome score together as JA4 and JA4H. That’s a TCP-side problem, and it’s one we already solve with a client that imitates a browser’s handshake. HTTP/3 fingerprinting is growing but still immature. Scrapfly is pretty direct about it: it “adds signals on top of” HTTP/2 instead of replacing it, real Chrome on HTTP/2 is still accepted on the vast majority of sites, and the scraper-on-HTTP/2 versus user-on-HTTP/3 gap is only “starting to become a signal on Cloudflare’s premium tier.” There’s also a catch worth keeping in mind: a scraper that speaks HTTP/3 through a non-browser QUIC stack shows a QUIC fingerprint that matches no real browser, so it can stand out just as easily as it blends in. In other words, a UDP proxy is what gets us onto HTTP/3 in the first place, but the stealth benefit only pays off if the client presents a QUIC fingerprint that a real browser would. The proxy just carries the traffic; making it look right is still our job.
The tooling has not caught up yet
The other half of the pitch is the tooling. The most common client for browserless scraping is curl_cffi, so the real question is whether it can actually do HTTP/3 in the setup a scraper normally runs in. We tested it (run_curl_cffi_http3.py), and you can find the code, as always, on our GitHub repository available for our paid readers, under the folder 109.UDP
The library is compiled with the QUIC stack, ngtcp2 and nghttp3, and on a plain direct request it does reach HTTP/3. It even reaches HTTP/3 with a full Chrome fingerprint if we use the low-level interface, so impersonation and HTTP/3 aren’t really in conflict, even if the first error makes it look that way.
high-level requests API:
plain, no impersonation, V3ONLY -> HTTP/3
Chrome impersonation, V3ONLY -> ERROR: QUIC needs at least TLS version 1.3
Chrome impersonation, HTTP proxy, V3 -> ERROR: HTTP/3 is not supported over an HTTP proxy
Chrome impersonation, SOCKS5, V3 -> ERROR: HTTP/3 is not supported over a SOCKS proxy
low-level Curl API (same impersonation):
impersonate chrome + V3ONLY -> HTTP/3That middle error in the high-level API is just a TLS-version conflict inside the requests wrapper, not a real limitation, since the low-level call combines the Chrome fingerprint with HTTP/3 and gets there fine. The lines that really matter are the proxy ones. curl refuses HTTP/3 over a proxy completely, both HTTP and SOCKS, and it refuses before it even connects, so this is curl saying no, not the proxy. It happens even with a proxy that could carry the UDP. And since a scraper always runs through a proxy, in practice curl_cffi ends up being HTTP/2 over TCP, and a UDP-capable proxy doesn’t change that at all.
So this is the honest picture on the request side. A proxy that carries UDP does its job for a client that tunnels its own UDP, but the popular HTTP clients refuse HTTP/3 over a proxy right now, so the benefit is stuck waiting for the tooling to catch up. The proxy capability is arriving before the clients that could use it, which is good to know before expecting HTTP/3 to flow through a scraper just because the proxy supports UDP.
The WebRTC leak, where UDP really bites




