Open methodology
How we reach a verdict
Everything runs in your browser. No data leaves your device unless you press Share report. The logic below is complete — nothing is hidden.
Why is this different?
Speedtest measures one nearby server. This test checks nearby routes, far routes, and the apps you use — then shows what works and what doesn't.
Speedtest
My ISP Sucks
One test covers
One nearby server
One test covers
Nearby routes, far routes, your apps
Download, upload, ping
Yes
Download, upload, ping
Yes
Streaming, games, cloud
Estimated from the number
Streaming, games, cloud
Checked on those services
What works and what doesn't
Not shown
What works and what doesn't
Shown
Who is responsible
Not named
Who is responsible
Wi‑Fi, ISP, or one service
You can send
The number
You can send
A complaint
Not affiliated with Ookla or Speedtest.
Run this test1 · What we probe
Four concentric layers, from your device outward:
Local gateway (preflight)
10 sequential HEAD requests to the nearest Cloudflare PoP (600 ms timeout each). Measures loss and jitter before anything else. If ≥ 2 time out or std-dev > 30 ms → path marked unstable.
Same-country nodes (near)
AWS S3 endpoints inside your country (matched by IP geolocation country code). Low score here = domestic ISP or routing issue.
International nodes (far)
16 AWS S3 regional endpoints worldwide (N. Virginia, Frankfurt, Tokyo, Singapore…). High score here while near nodes are fine = international gateway problem.
Service endpoints (profile)
15–25 HEAD requests to the services in your chosen profile (streaming / gaming / tech). Detects peering and blocking issues invisible to raw ping.
2 · Node health score
Each node gets a score from 0 (perfect) to 1 (broken). Near and far averages are kept separate.
score = 0.7 × (packetLoss / 100)
+ 0.3 × clamp((actualMs − expectedMs) / (expectedMs × 3), 0, 1)
expectedMs = max(10, distanceKm / 50) ← speed-of-light RTT baselineExample — Tel Aviv user → N. Virginia node (9 500 km)
expectedMs = max(10, 9 500 ÷ 50) = 190 ms
actualMs = 219 ms, packetLoss = 0 %
score = 0 + 0.3 × clamp((219 − 190) / (190 × 3), 0, 1) = 0.015 → healthy
nearScore < 0.25
Near: healthy
farScore > 0.35
Far: triggers Rule 6
farScore > 0.45
Far: degraded (Rule 5b)
3 · Service outlier
outlier if: status = "fail"
OR status = "slow" AND latencyMs ≥ cohortMedian × 2.5
slow = probe latency above 1 000 ms
ok under that line is not an outlierExample
Netflix 95 ms ✓ YouTube 88 ms ✓ Twitch 1 240 ms
cohortMedian = 88 ms → 1 240 ≥ 88 × 2.5 (220) → Twitch is an outlier
4 · Verdict rule chain
First match wins. Open DevTools → Console on any result page to see every rule that fired or was skipped.
Offline
connectivity = fail, and no other check reached the internet
→ down / local_issue
Local path unstable
Wi-Fi or cellular AND (preflight unstable OR jitter > 40 ms) AND farScore < 0.40
→ local_issue
DNS broken
device is online AND dns = fail
→ isp_issue
Specific service outlier
core healthy AND 1 ≤ outliers ≤ 40 % of services
→ service_issue
Most services degraded
core healthy AND badServiceFraction ≥ 50 %
→ isp_issue (peering)
Intl. traffic blocked
preflight loss = 0 AND nearScore < 0.25 AND farScore > 0.45 AND ≥ 3 far nodes
→ isp_issue (gateway)
Core path / far degraded
any test = fail OR farScore > 0.35
→ isp_issue
Soft degradation
any test = warn (no harder rule fired)
→ local_issue or isp_issue (medium)
All clear
→ healthy
5 · Plan delivery
ratio = measuredDown / promisedDown ≥ 0.80 → "As advertised" ✓ ≥ 0.50 → "Underdelivering" ~ < 0.50 → "Far below plan" ✗
Only annotates the report — does not change the culprit verdict.
6 · Privacy
All probes run in your browser. Nothing is sent to our server unless you press Share report.
Shared records store: verdict, scores, ISP name, country, medium. No IP addresses are stored.