Getting Started
The SpeedOf.Me API allows you to embed an internet speed test directly into your website or web application. The API uses a JavaScript interface that handles all the complexity of running speed tests.
Quick Start
Follow these three steps to integrate the SpeedOf.Me speed test:
1. Include the API Script
Add the SpeedOf.Me API script to your HTML page:
<script src="//speedof.me/api/api.js"></script>
speedof.me to ensure you have the latest version.
2. Configure the API
Set your API key and registered domain:
SomApi.account = "YOUR_API_KEY"; // Your API key from the portal
SomApi.domainName = "yourdomain.com"; // Your registered domain
3. Handle Results
Set up callbacks to receive test results:
SomApi.onTestCompleted = function(result) {
console.log("Download: " + result.download + " Mbps");
console.log("Upload: " + result.upload + " Mbps");
console.log("Latency: " + result.latency + " ms");
};
SomApi.onError = function(error) {
console.error("Error: " + error.message);
};
// Start the test
SomApi.startTest();
Configuration
Configure the API behavior using the SomApi global object.
SomApi.account
Your unique API key provided when you register. Format: SOMxxxxxxxxxx
SomApi.domainName
The domain where your speed test is hosted. Supports wildcards: *.example.com
SomApi.domainName in your JavaScript code, and the actual website domain must all match.
SomApi.config
Fine-tune the speed test behavior with these configuration options:
| Property | Type | Default | Description |
|---|---|---|---|
sustainTime |
number | 6 | Controls how long to sustain each download sample (1-8 seconds). Lower values (1-2) = faster but less accurate tests. Higher values (6-8) = slower but more accurate results. The actual download test takes 1-10s at sustainTime=1, or 8-87s at sustainTime=8. Upload time is also affected since its sample size depends on the last download. |
uploadTestEnabled |
boolean | true | Enable or disable the upload speed test. |
latencyTestEnabled |
boolean | true | Enable or disable latency (ping) and jitter measurement. |
testServerEnabled |
boolean | true | Enable or disable detection of the CDN test server location. |
userInfoEnabled |
boolean | true | Enable or disable fetching user IP address and hostname. |
progress.enabled |
boolean | true | Enable or disable progress callbacks during the test. |
progress.verbose |
boolean | false | Enable verbose mode for more frequent progress updates with current speed. |
maxTestPass |
number | 0 (auto) | Maximum test passes (8-11). Controls data usage. 0 = auto-detect based on speed. |
testTimeout |
number | 300 | Overall wall clock cap for the whole test, in seconds. If the test has not finished when it elapses, the test is aborted and onError fires with code 2004. 0 disables the cap; values below 30 are raised to 30; maximum 1800. |
Data Usage
Data consumption depends on connection speed. Use maxTestPass to limit bandwidth consumption per test:
| maxTestPass | Largest Sample | Max Bandwidth per Test |
|---|---|---|
| 0 (default) | No restrictions | 256 MB |
| 8 | 16 MB | 32 MB |
| 9 | 32 MB | 64 MB |
| 10 | 64 MB | 128 MB |
| 11 | 128 MB | 256 MB |
SomApi.config.maxTestPass = 8 (max 32 MB) or disable upload with SomApi.config.uploadTestEnabled = false.
Localhost Development
Register localhost in your API account, then use it in your JavaScript code:
SomApi.domainName = "localhost";
If you are using a port other than 80, include the port in your JavaScript code:
SomApi.domainName = "localhost:8080";
Starting a Local Server
If you don't have a local web server running, use one of these commands:
# Python (built-in)
python -m http.server 8080
# Node.js (npx - no install needed)
npx serve -p 8080
# Node.js (alternative)
npx http-server -p 8080
Then open http://localhost:8080 in your browser.
Example Configuration
// Configure the API
SomApi.account = "SOM_YOUR_API_KEY";
SomApi.domainName = "*.example.com";
// Customize test behavior
SomApi.config.sustainTime = 6; // Longer test for accuracy
SomApi.config.uploadTestEnabled = true;
SomApi.config.latencyTestEnabled = true;
SomApi.config.progress.enabled = true;
SomApi.config.progress.verbose = true; // Get real-time speed updates
SomApi.abortTest()
Cancels the ongoing test, if any. Safe to call at any time; it does nothing when no test is running. No callbacks fire for the aborted run, and startTest() can be called again immediately.
// e.g. wire a cancel button
document.getElementById("cancelBtn").onclick = function() {
SomApi.abortTest();
};
Callbacks
The API uses callback functions to communicate test progress and results.
onTestCompleted
Called when the speed test completes successfully. Receives a result object with all test metrics.
SomApi.onTestCompleted = function(result) {
// Speed results
console.log("Download Speed: " + result.download + " Mbps");
console.log("Upload Speed: " + result.upload + " Mbps");
console.log("Max Download: " + result.maxDownload + " Mbps");
console.log("Max Upload: " + result.maxUpload + " Mbps");
// Latency results
console.log("Latency: " + result.latency + " ms");
console.log("Jitter: " + result.jitter + " ms");
// Additional info
console.log("Test Server: " + result.testServer);
console.log("IP Address: " + result.ip_address);
console.log("Hostname: " + result.hostname);
console.log("Test Date: " + result.testDate);
};
onProgress
Called during the test to report progress. Enable with SomApi.config.progress.enabled = true.
SomApi.onProgress = function(progress) {
console.log("Phase: " + progress.type); // "download", "upload", or "latency"
console.log("Pass: " + progress.pass); // Current pass number
console.log("Progress: " + progress.percentDone + "%");
// Available in verbose mode
if (progress.currentSpeed) {
console.log("Current Speed: " + progress.currentSpeed + " Mbps");
}
// Status message
console.log("Status: " + progress.message);
};
onError
Called if an error occurs during the test.
SomApi.onError = function(error) {
console.error("Error Code: " + error.code);
console.error("Error Message: " + error.message);
// Handle specific errors
switch(error.code) {
case 1001:
console.log("Invalid API key");
break;
case 1002:
console.log("Domain not registered");
break;
default:
console.log("Test failed");
}
};
Result Objects
Test Result Object
The onTestCompleted callback receives an object with these properties:
| Property | Type | Description |
|---|---|---|
download |
number | Average download speed in Mbps |
upload |
number | Average upload speed in Mbps |
maxDownload |
number | Peak download speed in Mbps |
maxUpload |
number | Peak upload speed in Mbps |
latency |
number | Minimum latency (ping) in milliseconds |
jitter |
number | Latency variance in milliseconds |
testServer |
string | Test server location (e.g., "Los Angeles 1", "New York 2") or "Unknown" |
ip_address |
string | Client's public IP address |
hostname |
string | Reverse DNS hostname (if available) |
userAgent |
string | Browser user agent string |
testDate |
string | ISO 8601 timestamp of test completion |
Progress Object
The onProgress callback receives an object with these properties:
| Property | Type | Description |
|---|---|---|
type |
string | Test phase: "download", "upload", or "latency" |
pass |
number | Current pass number (1-based). Empty for latency phase. |
percentDone |
number | Percentage complete (0-100) |
currentSpeed |
number | Current speed in Mbps (verbose mode only) |
maxSpeed |
number | Peak speed so far in Mbps (verbose mode only) |
Error Codes
API Validation Errors
These errors occur during API key and domain validation:
| Code | Message | Cause |
|---|---|---|
1001 |
Invalid account | API key not found or account is inactive |
1002 |
Domain mismatch | The page URL doesn't match any registered domains |
Speed Test Errors
These errors occur during the actual speed test:
| Code | Message | Cause |
|---|---|---|
2001 |
Test error | Download or upload test failed |
2002 |
Invalid server response | JSON parsing error from CDN server |
2003 |
Request timeout | Network timeout during test |
2004 |
Test timeout | The test did not finish within config.testTimeout seconds (default 300) and was aborted |
2005 |
Speed test could not start (status n) | The account validation call could not complete. The status is in the message: 0 means the request never left the browser, so an ad blocker, content blocker, extension or firewall stopped it, or the connection dropped. Any other value is the status the server returned |
2006 |
Speed test engine did not load | The hidden test engine iframe never became ready, so no test could be started. Usually the same causes as 2005 one step earlier, or a frame-src Content-Security-Policy on your page that blocks speedof.me |
SomApi.domainName matches one of the domains registered in your API Portal account. If you receive error 2005 with status 0, or error 2006, the request was stopped before it left the browser, which is almost always an ad blocker, content blocker or privacy extension on the visitor's device rather than a problem with your integration. The exception worth checking is a frame-src Content-Security-Policy on your own page: it must allow https://speedof.me, or the engine iframe can never load and every test fails with 2006.
Advanced Topics
Mobile App Integration
The SpeedOf.Me API is JavaScript-based and requires a web browser environment. To integrate with native mobile apps:
- Host your speed test HTML page on a domain registered with your API account (e.g.,
yourdomain.com/speedtest.html) - Load that page in a WebView (iOS or Android) within your app
- Use JavaScript bridges to communicate results back to your native code
iOS (WKWebView)
Use WKWebView with a JavaScript message handler to receive results:
// In your WKWebView configuration
let config = WKWebViewConfiguration()
config.userContentController.add(self, name: "speedTestHandler")
// JavaScript in the WebView calls:
// window.webkit.messageHandlers.speedTestHandler.postMessage(result);
Android (WebView)
Use addJavascriptInterface to bridge JavaScript and native code:
// Enable JavaScript
webView.getSettings().setJavaScriptEnabled(true);
// Add interface for JavaScript to call native code
webView.addJavascriptInterface(new SpeedTestInterface(), "Android");
// In JavaScript:
// Android.onTestCompleted(JSON.stringify(result));
@JavascriptInterface annotation (required for API 17+).
Examples
Basic Sample
<!DOCTYPE html>
<html>
<head>
<script src="//speedof.me/api/api.js"></script>
</head>
<body>
<button onclick="startTest()">Start Speed Test</button>
<div id="results"></div>
<script>
// Configure the API
SomApi.account = "SOM_YOUR_API_KEY"; // Replace with your API key
SomApi.domainName = "yourdomain.com"; // Replace with your domain
SomApi.config.sustainTime = 6; // Test duration: 1-8 seconds
// Handle results
SomApi.onTestCompleted = function(result) {
document.getElementById('results').innerHTML =
'<p>Download: ' + result.download + ' Mbps</p>' +
'<p>Upload: ' + result.upload + ' Mbps</p>' +
'<p>Latency: ' + result.latency + ' ms</p>' +
'<p>Jitter: ' + result.jitter + ' ms</p>';
};
// Handle errors
SomApi.onError = function(error) {
alert('Error ' + error.code + ': ' + error.message);
};
function startTest() {
document.getElementById('results').innerHTML = 'Testing...';
SomApi.startTest();
}
</script>
</body>
</html>
More Examples
Ready-to-use integrations for React, Vue, Angular, iOS, Android, Flutter, and more.
Browse All ExamplesQuick Links
- Live Demos - Basic and advanced samples with progress updates
- Documentation - Copy-paste code examples
MCP / CLI / SDK
Beyond web embedding, you can use our npm package for AI agents, command-line tools, or Node.js applications.
npm i @speedofme/mcp
Requirements
- Node.js 18+
- API Secret - Different from API Key (see below)
Getting Your API Secret
The API Secret is different from your API Key. To get your API Secret:
- Log in to the API Portal
- Go to Settings
- Click Generate to create your API Secret (first time only)
- Copy your API Secret from the modal (you won't be able to see it again)
MCP & Agent Integrations
Use SpeedOf.Me with AI coding assistants and agent frameworks. Choose your client below:
MCP Clients
Claude Code
Run this command in your terminal:
claude mcp add-json speedofme '{"type":"stdio","command":"npx","args":["-y","@speedofme/mcp"],"env":{"SOM_API_SECRET":"your-api-secret"}}'
Claude Desktop
Add to your config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Cursor
Add to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):
{
"mcpServers": {
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Zed
Add to ~/.config/zed/settings.json:
{
"context_servers": {
"speedofme": {
"command": {
"path": "npx",
"args": ["-y", "@speedofme/mcp"]
},
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
VS Code (Copilot)
Add to .vscode/mcp.json (workspace) or via "MCP: Open User Configuration" command:
{
"servers": {
"speedofme": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Cline
Add via the MCP Servers icon in the Cline pane (cline_mcp_settings.json):
{
"mcpServers": {
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Continue
Add to your config.yaml:
mcpServers:
- name: speedofme
command: npx
args:
- "-y"
- "@speedofme/mcp"
env:
SOM_API_SECRET: "your-api-secret"
JetBrains
Go to Settings → Tools → MCP Server → Add Server, or copy this config:
{
"mcpServers": {
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"env": {
"SOM_API_SECRET": "your-api-secret"
}
}
}
}
Goose
Add to ~/.config/goose/config.yaml:
extensions:
speedofme:
name: SpeedOf.Me
cmd: npx
args: [-y, "@speedofme/mcp"]
enabled: true
envs:
SOM_API_SECRET: "your-api-secret"
type: stdio
timeout: 300
Available Tools
| Tool | Description |
|---|---|
run_speed_test |
Run a speed test with optional parameters |
get_test_history |
Get historical test results |
Tool Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
tests |
string[] | all | Tests to run: download, upload, latency |
sustainTime |
number | 6 | Seconds per sample (1-8). Lower = faster, higher = more accurate |
Available Resources
| Resource | Description |
|---|---|
speedofme://history |
Recent test results (JSON) |
speedofme://config |
SDK configuration and status |
Agent Frameworks
Integrate SpeedOf.Me into your AI agent applications:
LangChain / LangGraph
Install: pip install langchain-mcp-adapters
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
client = MultiServerMCPClient({
"speedofme": {
"command": "npx",
"args": ["-y", "@speedofme/mcp"],
"transport": "stdio",
"env": {"SOM_API_SECRET": "your-api-secret"}
}
})
tools = await client.get_tools()
agent = create_react_agent(model, tools)
result = await agent.ainvoke({
"messages": [("user", "Run a speed test")]
})
LlamaIndex
Install: pip install llama-index-tools-mcp
from llama_index.tools.mcp import BasicMCPClient
from llama_index.agent.openai import OpenAIAgent
client = BasicMCPClient("npx", args=["-y", "@speedofme/mcp"])
tools = await client.list_tools()
agent = OpenAIAgent.from_tools(tools, llm=llm)
response = agent.chat("Run a speed test")
AutoGen
Install: pip install autogen-ext[mcp]
from autogen_ext.tools.mcp import StdioServerParams, mcp_server_tools
from autogen_agentchat.agents import AssistantAgent
server_params = StdioServerParams(
command="npx",
args=["-y", "@speedofme/mcp"],
env={"SOM_API_SECRET": "your-api-secret"}
)
tools = await mcp_server_tools(server_params)
agent = AssistantAgent(
name="assistant",
model_client=model_client,
tools=tools
)
CrewAI
Install: pip install crewai-tools[mcp]
from crewai import Agent
from crewai.mcp import MCPServerStdio
agent = Agent(
role="Network Analyst",
goal="Assess connection quality",
mcps=[
MCPServerStdio(
command="npx",
args=["-y", "@speedofme/mcp"],
env={"SOM_API_SECRET": "your-api-secret"}
)
]
)
Semantic Kernel (.NET)
NuGet: Microsoft.SemanticKernel.Core (1.44.0+)
using Microsoft.SemanticKernel;
using ModelContextProtocol.Client;
await using var mcpClient = await McpClientFactory.CreateAsync(
new StdioClientTransport(new() {
Name = "speedofme",
Command = "npx",
Arguments = ["-y", "@speedofme/mcp"],
}));
var tools = await mcpClient.ListToolsAsync();
kernel.Plugins.AddFromFunctions("SpeedOfMe",
tools.Select(t => t.AsKernelFunction()));
var result = await kernel.InvokePromptAsync(
"Run a speed test and summarize the results");
Semantic Kernel (Python)
Install: pip install semantic-kernel>=1.28.1
from semantic_kernel import Kernel
from semantic_kernel.connectors.mcp import MCPStdioPlugin
kernel = Kernel()
plugin = MCPStdioPlugin(
command="npx",
args=["-y", "@speedofme/mcp"],
env={"SOM_API_SECRET": "your-api-secret"}
)
kernel.add_plugin(plugin, "speedofme")
result = await kernel.invoke_prompt(
"Run a speed test and tell me the results")
CLI
Run speed tests directly from the command line.
Quick Start
# Set your API secret
export SOM_API_SECRET=your-api-secret
# Run a speed test with progress output
npx -y @speedofme/mcp --progress
Common Commands
| Command | Description |
|---|---|
npx @speedofme/mcp --progress |
Run test with progress output |
npx @speedofme/mcp --json |
Output results as JSON |
npx @speedofme/mcp --tests download,latency |
Run specific tests only |
npx @speedofme/mcp history |
View test history |
Node.js SDK
Integrate speed testing into your Node.js applications.
Example
const { SpeedTest } = require('@speedofme/mcp');
const test = new SpeedTest({
apiSecret: process.env.SOM_API_SECRET
});
const result = await test.run();
console.log("Download: " + result.download + " Mbps");
console.log("Upload: " + result.upload + " Mbps");
console.log("Latency: " + result.latency + " ms");
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
apiSecret |
string | - | Your API Secret (required) |
sustainTime |
number | 6 | Seconds per sample (1-8) |
saveHistory |
boolean | true | Save results to local history |
tests |
string[] | all | Tests to run: download, upload, latency |
See the npm package for complete documentation.
Need help? Visit the API Portal or contact support.
© 2026 SpeedOf.Me