Skip to main content

Simplest possible usage

The SDK starts automatically on instantiation. Assign onFinish before the event loop yields to capture the final results:
import SpeedTest from '@cloudflare/speedtest';

new SpeedTest().onFinish = results => console.log(results.getSummary());
getSummary() returns an object with the computed metrics:
{
  "download": 94500000,
  "upload": 42000000,
  "latency": 12,
  "jitter": 1.5,
  "downLoadedLatency": 18,
  "downLoadedJitter": 2.1,
  "upLoadedLatency": 20,
  "upLoadedJitter": 2.8,
  "packetLoss": 0
}
Bandwidth values (download, upload) are reported in bits per second (bps). Divide by 1e6 to convert to Mbps.

Manual start

Set autoStart: false to construct the engine without immediately beginning measurements. Call play() when you are ready to start — for example, in response to a user action.
import SpeedTest from '@cloudflare/speedtest';

const engine = new SpeedTest({ autoStart: false });

engine.onFinish = results => {
  console.log(results.getSummary());
};

// Start the test whenever you're ready
engine.play();

Complete example with all event handlers

This example is derived from the basic-page demo and wires up every available event handler.
import SpeedTest from '@cloudflare/speedtest';

const engine = new SpeedTest({ autoStart: false });

// Fires whenever the engine starts or stops
engine.onRunningChange = running => {
  console.log(running ? 'Test is running...' : 'Test stopped.');
};

// Fires after each individual measurement completes
engine.onResultsChange = ({ type }) => {
  if (!engine.isFinished) {
    // Show intermediate results while the test is still running
    const summary = engine.results.getSummary();
    console.log(`Updated measurement: ${type}`, summary);
  }
};

// Fires once when all measurements are complete
engine.onFinish = results => {
  const summary = results.getSummary();
  const scores = results.getScores();

  console.log('Final summary:', summary);
  console.log('AIM scores:', scores);
};

// Fires if an error occurs during any measurement
engine.onError = error => {
  console.error('Measurement error:', error);
};

engine.play();
onResultsChange fires frequently during the test. For UI updates, check engine.isFinished to distinguish intermediate updates from the final state, and consider throttling DOM writes to avoid jank.

Play, pause, and restart

The engine exposes play(), pause(), and restart() methods for full interactive control.
import SpeedTest from '@cloudflare/speedtest';

const engine = new SpeedTest({ autoStart: false });

engine.onRunningChange = running => {
  startBtn.disabled = running;
  pauseBtn.disabled = !running;
};

engine.onResultsChange = () => {
  const { download, upload, latency, jitter } = engine.results.getSummary();
  displayResults({ download, upload, latency, jitter });
};

engine.onFinish = results => {
  console.log('Finished:', results.getSummary());
};

// Wire up buttons
startBtn.onclick = () => engine.play();
pauseBtn.onclick = () => engine.pause();
restartBtn.onclick = () => engine.restart();
1

play()

Starts the measurement sequence, or resumes from a paused state. Does nothing if the engine is already running or has finished.
2

pause()

Pauses the current measurement. The engine preserves all results collected so far. Call play() again to resume from where it left off.
3

restart()

Clears all results and restarts the full measurement sequence from the beginning.

Checking engine state

Two read-only boolean getters let you inspect the engine at any point:
const engine = new SpeedTest();

// Check if measurements are currently in progress
if (engine.isRunning) {
  console.log('Test is active');
}

// Check if all measurements have completed
if (engine.isFinished) {
  console.log('Test is done, results are final');
}
GetterDescription
isRunningtrue while measurements are actively being performed.
isFinishedtrue once all configured measurements have completed.
Both getters return false before play() is first called.

Displaying bandwidth in Mbps

getDownloadBandwidth(), getUploadBandwidth(), and getSummary() all return bandwidth values in bits per second (bps). Convert to Megabits per second for display:
engine.onFinish = results => {
  const summary = results.getSummary();

  const downloadMbps = summary.download / 1e6;
  const uploadMbps   = summary.upload   / 1e6;

  console.log(`Download: ${downloadMbps.toFixed(1)} Mbps`);
  console.log(`Upload:   ${uploadMbps.toFixed(1)} Mbps`);
};
You can apply the same conversion to individual data points from getDownloadBandwidthPoints() and getUploadBandwidthPoints():
const points = engine.results.getDownloadBandwidthPoints();

const mbpsValues = points.map(p => p.bps / 1e6);
console.log('Download samples (Mbps):', mbpsValues);

Build docs developers (and LLMs) love