GET
/health
Simple liveness check. Returns {"status":"ok"}.
HTTP API · no client install
Use these same-origin endpoints to probe latency, measure download and upload throughput, and optionally save a shareable result.
window.location.origin
GET /api/v1/version
GET /api/v1/ping 10–20 times.
GET /api/v1/download?duration=5 and count
bytes client-side.
application/octet-stream bodies to
POST /api/v1/upload until your target duration ends.
POST /api/v1/results.
/health
Simple liveness check. Returns {"status":"ok"}.
/api/v1/versionServer version and display name.
/api/v1/pingLatency probe plus observed client IP and IPv6 flag.
/api/v1/download
Binary stream. Query: duration=1..300,
chunk=65536..4194304.
/api/v1/uploadReads an octet-stream body and returns bytes, duration, and throughput.
/api/v1/resultsSave a result summary. Returns an 8-character result ID.
async function ping(base = location.origin) {
const start = performance.now();
const res = await fetch(`${base}/api/v1/ping`, { cache: "no-store" });
if (!res.ok) throw new Error(`ping failed: ${res.status}`);
return { latencyMs: performance.now() - start, ...(await res.json()) };
}
async function downloadMbps(seconds = 5, base = location.origin) {
const start = performance.now();
const res = await fetch(
`${base}/api/v1/download?duration=${seconds}&chunk=1048576`,
{ cache: "no-store" },
);
if (!res.ok || !res.body) throw new Error(`download failed: ${res.status}`);
const reader = res.body.getReader();
let bytes = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
bytes += value.byteLength;
}
const elapsed = (performance.now() - start) / 1000;
return (bytes * 8) / elapsed / 1_000_000;
}
async function uploadOnce(size = 1048576, base = location.origin) {
const payload = new Uint8Array(size);
crypto.getRandomValues(payload);
const res = await fetch(`${base}/api/v1/upload`, {
method: "POST",
headers: { "Content-Type": "application/octet-stream" },
body: payload,
});
if (!res.ok) throw new Error(`upload failed: ${res.status}`);
return res.json();
}
Retry-After when present.