Most proxy benchmarks you'll find are vendor marketing: a success rate with no methodology, no failure counts, no raw data. We run a residential proxy network, and we wanted numbers we could actually defend — so we benchmarked ourselves the way we'd want a third party to do it, and published every row.
Here's what 10,000 real requests look like, and what surprised us.
The setup
- 10,000 HTTPS requests to
https://www.cloudflare.com/cdn-cgi/trace— small, anycast, and it echoes the exit IP and country back at you. - 5 target countries (US, UK, Germany, Japan, Brazil) × 2,000 requests each.
- Every request forced a fresh session (new exit IP requested from the pool each time).
- Plain
curl, concurrency 20, 30s timeout, zero retries. Every failure stays in the dataset. - Vantage point: a server in Tokyo (AS3258).
A request only counts as a success if it returned HTTP 200 within the timeout — DNS, proxy CONNECT, TLS handshake and body included.
The numbers
| Country | Success | Median | p95 | Unique exit IPs (of 2,000) |
|---|---|---|---|---|
| US | 99.80% | 2.00s | 7.27s | 1,827 |
| UK | 99.80% | 2.37s | 8.23s | 1,533 |
| Germany | 99.75% | 2.39s | 12.22s | 1,651 |
| Japan | 99.70% | 2.03s | 14.01s | 1,026 |
| Brazil | 99.30% | 2.73s | 17.18s | 1,399 |
Overall: 99.67% success, 7,436 unique exit IPs across 10,000 requests. Geo-targeting accuracy was 98.9–100% per country.
Three things that surprised us
1. The tail is 5–6× the median. Medians cluster tightly at 2.0–2.7s everywhere, but p95 stretches to 12–17s in Germany, Japan and Brazil. If you set client timeouts based on the median, you'll drop a meaningful slice of otherwise-successful requests. Budget for the tail: 20–30s timeouts for residential traffic.
2. 74% of requests got a globally unique IP. With a forced new session per request, 7,436 of 10,000 requests exited through an address no other request in the test saw. The US pool was the deepest: 1,827 unique IPs in 2,000 requests (91%).
3. IPv6 is a big share of real residential exits. Between 42% and 76% of exits per country were IPv6. If your target or your tooling silently breaks on IPv6, that's a chunk of your error budget gone before you've done anything wrong.
Reproduce it (please do)
The whole thing is one loop:
for i in $(seq 1 2000); do
curl -s -o /dev/null -m 30 \
-w "%{http_code},%{time_total},%{time_starttransfer}\n" \
-x "http://USER-country-us-session-$i:PASS@gateway:port" \
https://www.cloudflare.com/cdn-cgi/trace
done
Point it at any provider, diff the results. Running this against a competitor takes an afternoon, which is exactly why we think publishing raw data should be table stakes in this industry.
Honest limitations
- One vantage point (Tokyo), one small target. A heavy page on a slow origin behaves differently — this measures the network, not your target site.
- Success against Cloudflare's trace endpoint ≠ success against aggressive bot defenses. That depends on your client fingerprint as much as the IP.
- It's our own network, measured by us. That's why the raw CSV (exit IPs anonymized to /24 & /48) and full methodology are public — verify, don't trust.
Full write-up + downloadable CSV (CC BY 4.0): roamproxy.com/residential-proxy-benchmark · code samples: github.com/roamproxy/proxy-examples
Top comments (0)