Most speed tests show you a number and leave it at that. This page is the whole method: which servers we talk to, how we count the bytes, how the ping is calculated, and — the part nobody publishes — the situations where our result is flattering rather than accurate.
We think you should be able to check our homework. A speed test is a measurement instrument, and an instrument you can't inspect is just a number with a logo on it.
Run the test →Free · No signup · ~10 seconds| What | How |
|---|---|
| Servers | Cloudflare edge |
| Download | 6 streams · 12 s |
| Upload | 3 streams · 12 s |
| Ping | TCP RTT, 6 samples |
| Warm-up ignored | First 1.5 s |
| Account needed | No |
We use Cloudflare's public measurement endpoints, speed.cloudflare.com/__down and
__up. Cloudflare runs edge servers in hundreds of cities and routes you to a nearby one
automatically, which is why there is no server picker on our homepage.
We removed the server picker deliberately. Early on we had one, and it was theatre — the requests went to whichever Cloudflare edge was closest regardless of what the dropdown said. A control that doesn't control anything is worse than no control, so it went.
We open six parallel streams, each requesting a 50 MB chunk, and run for 12 seconds. Rather than timing a completed file transfer, we read the response with a stream reader and add up bytes as they land. That gives a continuous rate instead of one average at the end, which is what makes the on-screen needle move in real time rather than jumping once.
Six streams is not padding. A single TCP connection often can't saturate a fast line on its own because of how congestion control ramps up, which is why single-stream tests under-report gigabit connections.
Every download request carries a counter appended to the URL. That's a cache-buster: without it, a carrier-side proxy can serve the same 50 MB from a local cache and report a speed that never touched the internet. We have seen that inflate results dramatically on mobile networks.
The first 1.5 seconds are thrown away before averaging. Connections need a moment to ramp up, and including that ramp drags the average below what the line actually sustains.
Upload measurement is where most browser-based tests quietly break, and it took us three attempts.
Attempt one used XMLHttpRequest and listened to
xhr.upload.onprogress, which is the textbook approach. It does not work here: attaching that
listener causes the browser to send a CORS preflight request, which Cloudflare's __up endpoint
rejects, and the whole request fails with status 0.
Attempt two counted whole completed POSTs. That works on a fast wired line and falls apart on mobile upload, which is often ten to twenty times slower than the download. If no chunk finishes inside the measurement window, the test reports 0.00 — not slow, but broken-looking.
What we do now is stream the request body: a ReadableStream sent with
duplex: 'half', filled from a 64 KB buffer, counting bytes as the browser pulls them.
Same granularity as the download. We run three streams for 12 seconds with 128 KB
chunks — deliberately small, so that even a slow mobile uplink completes several inside the window.
Streaming upload isn't supported everywhere. Firefox doesn't have it, so we feature-detect and fall back to the completed-chunk method there. If you compare your result across browsers and Firefox reads a little coarser, that's why.
Most tests time how long a small HTTP request takes and call that ping. That number includes TLS negotiation, server processing, and whatever else the browser was busy with — it's usually noticeably higher than your actual network latency.
Cloudflare returns a server-timing header containing min_rtt: the true TCP
round-trip time in microseconds, measured by the server's own network stack. We read that instead. We
take six samples after one discarded warm-up request, and report the
lowest one.
Why the lowest rather than the average? Because latency spikes are your device, your Wi-Fi, or a busy moment — not a property of the path. The floor is the honest figure for how far away the server is. If the header is missing for any reason, we fall back to wall-clock timing, which reads higher.
The provider name comes from an IP-geolocation lookup (ipwho.is, with
ipapi.co as a fallback) against the public address you're connecting from. Nothing is
hardcoded, and it works the same whether you're on home broadband anywhere in the world or on a mobile
carrier.
Two honest limits. On a VPN you'll see the VPN provider, because that genuinely is who you're connecting through. And some carriers register their address blocks under a parent company or a wholesale network operator, so the name shown can be the owner rather than the brand on your bill.
This is the section a speed test is not supposed to write. We think it's the most useful part of the page.
If your ISP has a direct connection to Cloudflare — or hosts a Cloudflare edge inside its own network — the test barely leaves your provider. You get a real measurement of your line, and an optimistic picture of the internet beyond it. Downloads from a poorly-connected server will be slower than what we show. This affects every Cloudflare-based test, ours included.
On a gigabit plan the bottleneck is usually the Wi-Fi link, not the line. Test with a cable to see what you're paying for; test on Wi-Fi to see what your devices actually get. Both are true, and they answer different questions.
Any single run can catch a good or bad moment. Three runs a few minutes apart tell you far more than one, and running it at 9pm as well as at noon tells you whether your evenings are congested.
A console updating in another room or a cloud backup mid-sync competes with the test. We measure what's left over, which is honest but isn't your line's capacity.
If you can show that our method is wrong, or that a result is inconsistent with a measurement you trust more, tell us on our contact page. The upload method on this page is the third version because the first two were wrong; we would rather fix a fourth thing than defend a bad number.