BitStream Download

One file.
Two machines.
A real measurement.

BitStream is a point-to-point network performance tester that lives entirely in one HTML file. Open it on both ends of a link, press start, and measure throughput, latency, jitter and packet loss over the actual path — with nothing installed on either machine.

  • No install
  • No server
  • No dependencies
  • No telemetry in the tool
  • MIT licensed
PRBS-9 · xⁿ + x⁵ + 1 one of seven selectable payload patterns
BitStream results panel showing 33.23 Mbit/s received, 42.5 MB transferred, 0.000 percent packet loss, 4.204 ms jitter, zero reordered packets, a throughput graph over time, and a summary table listing bytes received, messages received, jitter and sender-limited status.
The results panel after a completed run. Throughput is measured at the receiving end, and every figure is exportable.
1
HTML file, nothing else to deploy
0
Dependencies, CDNs or build steps
0
Requests the tool sends anywhere at runtime
193
Assertions passing across two test suites

How it works

Three steps, no infrastructure in between.

Traffic moves over a WebRTC data channel — SCTP over DTLS over UDP — directly between the two machines. On the same subnet there is no relay and no proxy in the path, so the bytes genuinely cross the link you are testing.

STEP 1

Open the same file on both machines

Double-clicking it is enough — file:// is a secure context, which is all WebRTC needs. One machine becomes the server, the other the client. The server is started first, matching the habit from iperf.

The BitStream interface on first load, showing a five-step workflow: Role, Connect, Link check, Configure and Run, with the Role step offering Server and Client options.
A five-step stepper. Each step stays locked until the one before it completes.
STEP 2

Carry two codes between them

The server generates a session code; the client answers with a reply code. Each is a compressed, checksummed blob you paste across — no signalling server, no account, no internet connection required. Both codes show a checksum so you can confirm the paste landed intact.

The Connect step showing a generated session code of 686 characters with checksum FB5E77, a Copy button, and a second field holding the reply code pasted back from the client machine.
Codes are deflate-compressed and base64url-encoded. You never type them — copy, carry, paste.
STEP 3

Check the link, then load it

A latency baseline runs first, reported the way ping reports it — min, average, max and mean deviation, plus percentiles and the browser's own ICE round-trip time. Then the big green button loads the path.

The link check panel showing latency tiles for minimum, average, maximum, mean deviation, 95th percentile and ICE round-trip time, each reported in milliseconds.
These are application-layer round trips, not ICMP echoes — read them as an upper bound.

What it measures

Six numbers, each computed honestly.

Throughput

Application-layer goodput, measured at the receiving end rather than claimed by the sender. Reported per second and as an overall mean.

Latency

Round trips over the control channel as min / avg / max / mdev and p50, p95, p99, cross-checked against the browser's ICE connectivity-check RTT.

Jitter

RFC 3550 smoothed mean deviation of transit time. It works on the variation, so the unknown clock offset between two machines cancels out — no clock sync needed.

Packet loss

Counted against the sender's own message total, shipped over the control channel. The receiver cannot otherwise know how many messages were meant to arrive.

Reordering & duplication

Exact over a 65,536-packet window, using sequence numbers rather than sampling. Visible only in unreliable mode — the reliable channel repairs both by design.

Payload integrity

Received bytes verified against the exact bit pattern that was transmitted, so silent corruption surfaces instead of quietly inflating the throughput figure.

Controls

Set the variables that actually change the answer.

Transport mode, direction, duration, offered rate, message size, bit pattern and integrity checking. The client sets them and they apply to both ends automatically.

The Configure panel with dropdowns for transport mode set to reliable ordered TCP-like, direction client to server, duration ten seconds, offered rate unlimited, message size 8192 bytes, bit pattern PRBS-31, and payload integrity check sampled one in thirty-two.

Two settings people get wrong

Fix the rate if you care about loss or jitter. At unlimited rate you are deliberately overrunning the path, so the loss figure tells you how far past capacity you pushed — not what the path's loss characteristics are. A token-bucket pacer holds whatever rate you set.

Bit patterns matter on links that compress. All-zeros will sail through a compressing link at a flattering rate. Use PRBS-31 or random for a fair measurement — or use the compressible patterns deliberately, when compression is exactly what you are trying to detect.

Limits

What it will not pretend to do.

Browsers have no access to raw sockets. Rather than approximate these and quietly mislead you, BitStream leaves them out — and says so in the interface and in every exported report.

  • Traceroute Needs ICMP and TTL control. Not possible in a browser, and not approximable. Use traceroute or mtr.
  • ICMP ping The latency figures are application-layer round trips and carry a little browser scheduling overhead. Treat them as an upper bound.
  • Port selection ICE chooses ephemeral UDP ports. You cannot pin the test to a specific port.
  • QoS / DSCP marking Not exposed for data channels in any portable way.
  • Path MTU discovery The size control sets an application message size, not the IP MTU. Larger messages are fragmented by SCTP.

And the one that matters most: the browser is often the bottleneck

A data channel costs CPU — SCTP framing, DTLS encryption and JavaScript overhead all sit between you and the wire. On a fast link that cost, rather than the link, is usually what you hit. BitStream watches for it: it compares the achieved rate against the offered rate, tracks event-loop delay, and counts how often the transmit buffer filled. When the sender could not keep the channel fed, the result is labelled sender-limited in the interface and at the top of the report — a floor on the path's capacity, not a measurement of it.

The About the measurements panel inside the app, listing what is measured, a section headed What is deliberately not here covering traceroute, ICMP ping, port selection, QoS marking and true MTU discovery, and a closing section on reading the throughput number honestly.
This panel ships inside the tool itself, above the results — not buried in documentation.

Output

A report you can paste into a ticket.

Every run exports to Markdown with ISO-8601 timestamps and the local UTC offset, the full configuration, both machines' user agents, the negotiated candidate pair, per-second interval tables, the browser's own counters as a cross-check, and a complete event log. Warnings sit at the top, ahead of the numbers they qualify.

An exported Markdown report opened in a text editor, showing the test ID, ISO-8601 start and finish timestamps, wall clock duration, a test configuration table, an environment table listing both machines' browsers and the local and remote ICE candidates, and the beginning of a results table.
Plain Markdown — diffable, greppable, and readable without the tool.
The event log panel showing timestamped entries for data channels opening, the negotiated maximum SCTP message size, peer connection, configuration received, test start, the measured result of 33.23 Mbit/s with zero percent loss, and test completion.
Every state change is timestamped and travels with the report.

Verification

It tests itself, in one tab.

A tool that needs two machines to be useful should still be checkable on one. Append a query string and the same file runs its own suites — no second machine, no network.

# 122 unit assertions: RFC 3550 jitter vectors, PRBS periods,
# packet and signalling codecs, sequence accounting, report fixture
bitstream.html?selftest=1

# 71 assertions driving both peers in one page over real data channels,
# across reliable, unreliable, rate-limited and bidirectional runs
bitstream.html?loopback=1

The page title becomes PASS or FAIL, so both suites can be driven headlessly in CI.

Measure the link, not the tooling.

One file, downloaded twice. That is the whole setup.

  • Chromium, Firefox and Safari
  • Works fully offline
  • MIT licensed