My ISP Sucks

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.

1 · 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 (New York, 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 baseline

Example — Tel Aviv user → New York node (9 100 km)

expectedMs = max(10, 9 100 ÷ 50) = 182 ms

actualMs = 210 ms, packetLoss = 0 %

score = 0 + 0.3 × clamp((210 − 182) / (182 × 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  latencyMs > 400 ms  AND  latencyMs ≥ cohortMedian × 2.5

Example

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.

1

Offline

connectivity = fail

down / local_issue

2

Local path unstable

Wi-Fi or cellular AND (preflight unstable OR jitter > 40 ms) AND farScore < 0.40

local_issue

3

DNS broken

connectivity = pass AND dns = fail

isp_issue

4

Specific service outlier

core healthy AND 1 ≤ outliers ≤ 40 % of services

service_issue

5

Most services degraded

core healthy AND badServiceFraction ≥ 50 %

isp_issue (peering)

5b

Intl. traffic blocked

preflight loss = 0 AND nearScore < 0.25 AND farScore > 0.45 AND ≥ 3 far nodes

isp_issue (gateway)

6

Core path / far degraded

any test = fail OR farScore > 0.35

isp_issue

6b

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.

Full source: src/lib/diagnostics/verdict.ts · nodes.ts · preflight.ts