Data access and the API
English
Every number on this site is available as JSON: the rankings, the raw test records, per-tool statistics and the external observatories. This page lists the endpoints, their parameters, how often they change, and the terms for reusing the data.
8 menit baca · Diterbitkan 10 September 2026
The tables on this site are rendered from the same JSON endpoints described here, so anything you can see you can also fetch. There is no key, no sign-up and no rate limit on the read endpoints. The only things we ask for are attribution and a little restraint: cache what you fetch and don't poll faster than the data changes.
The short version
GET /api/rankings— the leaderboard for a filter tuple (period, location, OS, source).GET /api/results— every public test record, paged, newest first.GET /api/results/{id}— one record with its full detail blob.GET /api/provider/{name}— one tool: medians, breakdowns and a 90-day timeline.GET /api/observatory/*— the external observatories (OONI, Tor Metrics, Cloudflare Radar, IODA, GreatFire) per country.GET /api/intel/stats— aggregate IP-intelligence statistics from the fingerprint lab.GET /api/stats— site totals, the last sync run and the pulse ticks on the home page.
All responses are application/json; charset=utf-8 with { "ok": true, ... }; errors come back as { "ok": false, "error": "…" } with a 400 or 404 status. Paths are not locale-prefixed: /api/rankings is the same for every language.
Shared vocabulary
Several endpoints accept the same filters, spelled exactly as below (lower case).
| Parameter | Values | Default |
|---|---|---|
period |
today (24 h), week, month, 60days, 3months (90 d), all |
60days for rankings, all for a provider |
location |
mainland china, russia, iran, turkmenistan, other, all |
all |
os |
windows, android, macos, ios, linux, chromeos, all |
all |
source |
greatfire (imported), breakhub (measured here), all |
all |
The China key contains a space; in a URL write it as mainland%20china. Speeds are in bytes per second (divide by 125 000 for Mbit/s), latencies in milliseconds, stability as a percentage of successful image loads. Timestamps are ISO 8601 in UTC.
/api/rankings
Returns the leaderboard exactly as the home page shows it, including the eligibility rules described in how to read the rankings.
curl 'https://breakhub.org/api/rankings?period=60days&location=russia&os=android'
Extra parameters: servicesOnly (1/0, default 1: exclude self-hosted protocols from the ranked pool) and minTests (1–50, default 5). Unknown or malformed values fall back to the defaults rather than failing.
The body carries filters, counts (how many tools qualify per location and OS tab), tools (ranked first, then unranked, each with count, avgSpeed, avgLatency, avgStability, ranking, score, providerType, pricingModel and a sources breakdown), locationMedian (the medians over every test in the location) and upstream (GreatFire's latest snapshot, when one exists, re-ranked with our algorithm). Cached for 60 seconds.
/api/results
The raw records, including tests that ran without any tool (tool: "None"). Hidden rows are never returned.
curl 'https://breakhub.org/api/results?tool=Shadowrocket&location=mainland%20china&page=1&limit=100'
Parameters: the shared filters (invalid values return 400 here), tool (exact name), ipCountry (two-letter code), page (from 1) and limit (1–200, default 50). Each row has id, source, createdAt, location, tool, toolVersion, os, browser, ipCountry, speedAvg, latencyMedian, stabilityPct, reachOk/reachTotal and a streaming estimate. Page through with page; total tells you when to stop. Cached for 30 seconds.
/api/results/{id} returns one row with the detail object: the individual speed samples and URLs, per-domain latencies, image loads and reachability probes. Records imported from GreatFire (gf_… ids) also carry upstreamUrl pointing at the original page.
/api/provider/{name}
Everything on a tool page. The name is URL-encoded; period defaults to all and stat can be median (default) or mean.
curl 'https://breakhub.org/api/provider/Shadowrocket?period=3months'
The body has overall (count, medians, min/max), byLocation, byOs and byVersion groups, a daily timeline for the last 90 days, the 20 most recent rows, and upstream links. Unknown tools are a 404. Cached for 60 seconds.
/api/observatory/*
Public measurements from other projects, stored on our side so the pages stay up when the upstream is slow or blocked. Every route takes country (CN, RU, IR, TM) or location (the ranking key), and most take days.
| Route | days default / max |
What it returns |
|---|---|---|
/api/observatory/summary |
— | outage state, 7-day OONI anomalies, Tor bridge users, connection quality |
/api/observatory/reach |
14 / 90 | OONI web-connectivity anomaly rate per domain and day |
/api/observatory/tools |
30 / 90 | OONI circumvention-tool tests (Tor, Snowflake, Psiphon …) per day |
/api/observatory/tor |
90 / 366 | Tor Metrics bridge and relay users, by transport |
/api/observatory/quality |
28 / 90 | Cloudflare Radar bandwidth, latency and DNS time |
/api/observatory/outages |
30 / 90 | IODA and Radar outage events |
/api/observatory/greatfire |
— | GreatFire's blocked-domain list (China only) |
/api/observatory/status |
— | when each source last synced, and any error |
curl 'https://breakhub.org/api/observatory/outages?country=IR&days=60'
These are cached for 10 minutes and the underlying sync runs every six hours. Each source has its own terms; the observatory page names them next to every panel, and you should credit the original project when you reuse those figures.
/api/intel/stats
Aggregates from the IP-intelligence lookups in the fingerprint lab: the most-seen networks with their VPN/proxy/Tor/hosting shares, TLS fingerprint families by browser, and resolver prefixes seen by the DNS-leak test. No parameters; everything is aggregated (top 50 networks, low-count rows withheld) and no individual lookup is exposed. Cached for 5 minutes.
Freshness and caching
The GreatFire import runs hourly, tests taken on this site appear at once, and the observatories refresh every six hours. /api/stats includes lastSync so you can tell how old the imported rows are. Every endpoint sets a Cache-Control header; please honour it, and if you keep a copy, refreshing once an hour matches how often anything actually changes. A polite User-Agent with a contact address helps us reach you if something goes wrong.
There is also an Atom feed of these guides at /en/kb/feed.xml (swap the language code for the other locales).
Attribution and licence
Two kinds of data flow through these endpoints and they carry different terms.
Tests measured on this site (source: "breakhub") are published under Creative Commons Attribution 4.0. You may copy, redistribute and build on them, including commercially, as long as you credit "BreakHub (breakhub.org)" and link back where practical. Suggested citation: BreakHub, "Measured performance of network access tools", breakhub.org, retrieved YYYY-MM-DD.
Rows imported from GreatFire (source: "greatfire", ids starting with gf_) remain GreatFire's data. We redistribute them under the public terms of Circumvention Central; if you reuse them, credit GreatFire Circumvention Central as the source, not us, and check their site for the current terms. The upstreamUrl on each imported record points at the original.
The observatory routes relay OONI, Tor Metrics, Cloudflare Radar, IODA and GreatFire data under those projects' own licences. Our code, the rankings algorithm and the text of these guides are ours; ask before reproducing the guides at length.
What we would rather you didn't do
Scraping the HTML pages when the JSON exists, hammering /api/results with limit=200 in a tight loop, or presenting imported GreatFire rows as our measurements. None of this is enforced by a key today; it is enforced by the fact that the site is small and we would like to keep it open.