Passive network measurement
How it works
Bursts, not requests
Six images at once each look slow alone, because each is getting a slice of the link. Overlapping transfers merge into one burst: total bytes over the wall time it occupied.
Slow start, undone
A new connection's window doubles each round trip rather than opening at full speed. The ramp costs a predictable amount of time, subtracted only where the timings show a real handshake — never on a reused connection, which never paid it.
Regression across sizes
Duration is roughly overhead plus bytes over rate. Fit duration against size across a session and the rate falls out of the slope, the overhead out of the intercept.
A lower bound
Nothing in passive measurement makes a link look faster than it is; plenty makes it look slower. So every figure carries a confidence score, and a page too light to reveal anything says so instead of guessing.
Usage
import { Freeloader } from "./freeloader.js";
const freeloader = Freeloader.start(); // observes; never requests
freeloader.subscribe((e) => console.log(e.download.megabitsPerSecond, e.latency.roundTripMilliseconds));