speedtest-z automates major speed test sites with a web browser, capturing real user-experience network quality for continuous monitoring.
- Supports 8 speed test sites (Cloudflare, Netflix, Ookla, M-Lab, and more)
- Zabbix integration for continuous network quality monitoring
- Quick start:
pip install speedtest-z
- Runs speed tests on 8 different sites automatically (Cloudflare, Netflix/fast.com, Google Fiber, Ookla, Box-test, M-Lab, USEN, iNonius)
- Sends results to Zabbix via trapper items (using zappix)
- Optional Grafana Cloud integration via Prometheus Remote Write
- Optional OpenTelemetry (OTLP) metrics export
- Configurable test frequency per site (probability-based throttling)
- Screenshot capture for debugging
- Headless or GUI Chrome mode
- CLI with
--dry-run, site selection, etc. - systemd timer integration for scheduled execution
- Prerequisites
- Installation
- Configuration
- Usage
- Supported Test Sites
- Zabbix Integration
- Grafana Cloud Integration
- OpenTelemetry (OTLP) Integration
- Deployment (systemd)
- Troubleshooting
- License
- Python >= 3.10
- Google Chrome browser (not installable via pip -- must be installed separately)
brew install shigechika/tap/speedtest-zPre-built bottles are available for macOS Sonoma (14) and Sequoia (15) on Apple Silicon. Installation completes in seconds.
Download the .deb package for your distribution from GitHub Releases:
# Ubuntu 24.04 (Noble)
sudo dpkg -i speedtest-z_*~noble.deb
# Ubuntu 22.04 (Jammy)
sudo dpkg -i speedtest-z_*~jammy.debThe .deb package includes all Python dependencies in a self-contained virtualenv (/opt/venvs/speedtest-z/), systemd service/timer (installed disabled), and config files in /etc/speedtest-z/.
# Edit config
sudo vi /etc/speedtest-z/config.ini
# Enable scheduled execution (every 10 minutes)
sudo systemctl enable --now speedtest-z.timerDownload the .rpm package from GitHub Releases:
# RHEL 9 / Rocky Linux 9 / AlmaLinux 9
sudo dnf install python3.11
sudo rpm -ivh speedtest-z-*-1.el9.x86_64.rpmThe .rpm package has the same structure as the .deb package: self-contained virtualenv in /opt/venvs/speedtest-z/, systemd service/timer, and config files in /etc/speedtest-z/.
pip install speedtest-z
# or using uv
uv tool install speedtest-zgit clone https://github.com/shigechika/speedtest-z.git
cd speedtest-z
python3 -m venv .venv
. .venv/bin/activate
pip install -e .
# or using uv
uv syncpip install speedtest-z[grafana]
# or using uv
uv tool install "speedtest-z[grafana]"This installs cramjam for Snappy compression required by Prometheus Remote Write.
pip install speedtest-z[otel]
# or using uv
uv tool install "speedtest-z[otel]"This installs the OpenTelemetry SDK and OTLP HTTP exporter for sending metrics via OTLP.
pip install speedtest-z[completion]
eval "$(register-python-argcomplete speedtest-z)"Add the eval line to your shell profile (~/.bashrc or ~/.zshrc) to enable it permanently.
The configuration file is searched in the following order (-c / --config can override):
./config.iniin the current directory~/.config/speedtest-z/config.ini(XDG_CONFIG_HOME)/etc/speedtest-z/config.ini(system-wide, used by.debpackage)
Copy config.ini-sample to one of these locations and edit as needed.
[general]
# Run mode
dry_run = true # true = do not send data to backends
headless = false # true = run Chrome in headless mode
timeout = 30 # timeout in seconds for each test
# ookla_server = IPA CyberLab 400G # Ookla test server (omit for auto-select)
[zabbix]
# Zabbix server settings
enable = false # true = send results to Zabbix
server = 127.0.0.1
port = 10051
host = speedtest-agent # Zabbix host name for trapper items
[snapshot]
# Screenshot capture settings
enable = true
save_dir = ./snapshots
[frequency]
# Execution probability per site (0-100)
# 100 = always run, 50 = ~50% chance, 0 = disabled
cloudflare = 100
netflix = 100
google = 100
ookla = 50
boxtest = 50
mlab = 10
usen = 50
inonius = 50
# [grafana]
# # Grafana Cloud Prometheus Remote Write
# enable = false
# remote_write_url = https://prometheus-prod-XX-prod-XX.grafana.net/api/prom/push
# username =
# token =
# [otel]
# # OpenTelemetry (OTLP) metrics export
# enable = false
# endpoint = https://otlp-gateway-prod-XX.grafana.net/otlp
# # Comma-separated Key=Value pairs (same format as OTEL_EXPORTER_OTLP_HEADERS)
# headers = Authorization=Basic <base64-encoded-credentials>Note: The
dryrunkey (without underscore) is still supported for backward compatibility butdry_runis preferred.
An optional logging.ini file can be used to customize log output. The file is searched in the same order as config.ini:
./logging.iniin the current directory~/.config/speedtest-z/logging.ini(XDG_CONFIG_HOME)/etc/speedtest-z/logging.ini(system-wide)
If none is found, the default logging configuration (INFO level to stdout) is used.
speedtest-z [options] [site ...]
| Option | Description |
|---|---|
-V, --version |
Show program version and exit |
-c, --config CONFIG |
Config file path (default: ./config.ini or ~/.config/speedtest-z/config.ini) |
-n, --dry-run |
Test run (do not send data to Zabbix) |
--headless |
Run Chrome in headless mode |
--no-headless, --headed |
Run Chrome with GUI (non-headless) |
--timeout SECONDS |
Timeout in seconds for each test |
--list-sites |
List available test sites and exit |
--check |
Check site URL reachability and exit (no Chrome needed) |
-o, --output FORMAT |
Output format: zabbix (default), json, csv |
-d, --debug |
Enable debug output |
site |
Positional argument(s): test site(s) to run (default: all) |
When run from an interactive terminal (TTY), speedtest-z asks for confirmation before connecting to test sites. Non-interactive environments (cron, systemd, piped input) skip the prompt automatically.
$ speedtest-z -n
speedtest-z: connecting to 8 site(s) (cloudflare, netflix, ...)
Continue? [y/N]: y
# Run all test sites (dry-run)
speedtest-z -n
# Run specific sites
speedtest-z cloudflare netflix
# Run with GUI browser for debugging
speedtest-z --no-headless -d cloudflare
# List available sites
speedtest-z --list-sites
# Check if all test site URLs are reachable (no Chrome needed)
speedtest-z --check
# Check specific sites only
speedtest-z --check cloudflare netflix
# Output results as JSON (Zabbix send is skipped)
speedtest-z --dry-run --output json cloudflare 2>/dev/null
# Output results as CSV
speedtest-z --dry-run -o csv cloudflare netflix 2>/dev/null$ speedtest-z --dry-run
speedtest-z: connecting to 8 site(s) (cloudflare, netflix, google, ookla, boxtest, mlab, usen, inonius)
Continue? [y/N]: y
2026-02-25 15:00:01 [INFO] speedtest-z: START
2026-02-25 15:00:01 [INFO] Config loaded: config.ini
2026-02-25 15:00:01 [INFO] Initializing Chrome WebDriver...
2026-02-25 15:00:02 [INFO] cloudflare: OPEN
2026-02-25 15:00:09 [INFO] cloudflare: Test started
2026-02-25 15:00:58 [INFO] cloudflare: COMPLETED (Quality Scores appeared)
2026-02-25 15:00:58 [INFO] netflix: OPEN
2026-02-25 15:01:24 [INFO] netflix: COMPLETED (succeeded class detected)
2026-02-25 15:01:24 [INFO] google: OPEN
2026-02-25 15:01:51 [INFO] google: COMPLETED
2026-02-25 15:01:51 [INFO] ookla: OPEN (Attempt 1/3)
2026-02-25 15:02:31 [INFO] ookla: COMPLETED
2026-02-25 15:02:33 [INFO] boxtest: OPEN
2026-02-25 15:03:48 [INFO] boxtest: COMPLETED
2026-02-25 15:03:48 [INFO] mlab: OPEN
2026-02-25 15:04:36 [INFO] mlab: COMPLETED
2026-02-25 15:04:36 [INFO] usen: OPEN
2026-02-25 15:05:05 [INFO] usen: COMPLETED (speedtest_wait class removed)
2026-02-25 15:05:05 [INFO] inonius: OPEN
2026-02-25 15:06:02 [INFO] inonius: COMPLETED
2026-02-25 15:06:02 [INFO] speedtest-z: FINISH
All 8 sites completed in about 6 minutes.
| Site | URL | Metrics (Zabbix keys) |
|---|---|---|
cloudflare |
https://speed.cloudflare.com/ | download, upload, latency, jitter |
netflix |
https://fast.com/ | download, upload, latency, server-locations |
google |
http://speed.googlefiber.net/ | download, upload, ping |
ookla |
https://www.speedtest.net/ | download, upload, ping |
boxtest |
https://www.box-test.com/ | POP, DownloadSpeed, DownloadDuration, DownloadRTT, UploadSpeed, UploadDuration, UploadRTT, latency |
mlab |
https://speed.measurementlab.net/ | download, upload, latency, retrans |
usen |
https://speedtest.gate02.ne.jp/ | download, upload, ping, jitter |
inonius |
https://inonius.net/speedtest/ | IPv4/IPv6: DL, UL, RTT, JIT, MSS |
All Zabbix item keys are prefixed with the site name (e.g., cloudflare.download, usen.ping, inonius.IPv4_DL).
Note: Google Fiber (speed.googlefiber.net) and jumbo frames
speed.googlefiber.net does not support HTTPS (HTTP only) and has no AAAA records. In IPv6-only environments it is accessed via DNS64/NAT64, but if the NIC MTU is set to 9000 (jumbo frames), the page JavaScript fails to load and the screen stays blank. Set the MTU to 1500.
- Import the
speedtest-z_templates.yamltemplate into Zabbix. - All items are trapper type -- the agent pushes data to Zabbix using the zappix sender protocol.
- Set
enable = truein the[zabbix]section ofconfig.ini. - The
hostvalue inconfig.inimust match the host name registered in Zabbix.
speedtest-z can push metrics to Grafana Cloud via Prometheus Remote Write.
- Install with Grafana support:
pip install speedtest-z[grafana] - Add the
[grafana]section toconfig.ini:
[grafana]
enable = true
remote_write_url = https://prometheus-prod-XX-prod-XX.grafana.net/api/prom/push
username = <your-prometheus-username>
token = <your-grafana-cloud-api-token>- Metrics are sent as
speedtest_<metric>with asitelabel (e.g.,speedtest_download{site="cloudflare"}). - Both Zabbix and Grafana can be enabled simultaneously -- results are sent to all enabled backends.
speedtest-z can export metrics via OpenTelemetry Protocol (OTLP) to any OTLP-compatible backend.
- Install with OTel support:
pip install speedtest-z[otel] - Add the
[otel]section toconfig.ini:
[otel]
enable = true
endpoint = https://otlp-gateway-prod-XX.grafana.net/otlp
headers = Authorization=Basic <base64-encoded-credentials>- Metrics are sent as
speedtest_<metric>withsiteandhostlabels. - All three backends (Zabbix, Grafana, OTel) can be enabled simultaneously.
Note: As of Feb 2026, direct OTLP metrics ingestion (without a collector) on free tier accounts is supported by very few backends. Grafana Cloud is the most mature option. Mackerel, GCP Cloud Monitoring, and AWS CloudWatch currently support OTLP traces only; Datadog requires an allowlisted organization. Paid plans may offer broader OTLP metrics support.
Note: The
.deband.rpmpackages include systemd service/timer files pre-configured. Just runsudo systemctl enable --now speedtest-z.timerafter installing.
For manual (pip) installations, the deploy/ directory contains systemd unit files for scheduled execution:
| File | Description |
|---|---|
speedtest-z.service |
Service unit (runs speedtest-z from the venv) |
speedtest-z.timer |
Timer unit (runs every 6 minutes) |
SeleniumCleaner.cron |
Cron job to clean up stale Chrome temp files |
# Copy unit files
cp deploy/speedtest-z.service ~/.config/systemd/user/
cp deploy/speedtest-z.timer ~/.config/systemd/user/
# Reload and enable
systemctl --user daemon-reload
systemctl --user enable --now speedtest-z.timer
# Check status
systemctl --user status speedtest-z.timer
systemctl --user list-timersOptionally, install the cron job for cleaning up stale Chrome temporary directories:
sudo cp deploy/SeleniumCleaner.cron /etc/cron.d/SeleniumCleanerGot the fastest or slowest speed test result? We'd love to see it!
Submit your results via GitHub Issues with:
- Screenshot(s) from the
snapshots/directory - CLI log output (
speedtest-z --dry-run)
Whether it's blazing fast datacenter fiber or painfully slow hotel Wi-Fi, all results are welcome.
| Problem | Solution |
|---|---|
| Tofu characters (□□□) in USEN/iNonius snapshots on Linux | Install Japanese fonts: sudo apt install fonts-noto-cjk |
| ChromeDriver version mismatch error | Selenium Manager auto-downloads the matching driver. Update selenium package: pip install -U selenium |
| Site test hangs or times out | Increase timeout: speedtest-z --timeout 60 or check your network |
config.ini not found |
Place it in one of: ./, ~/.config/speedtest-z/, or /etc/speedtest-z/. Copy from config.ini-sample |
| Zabbix sender connection refused | Verify server and port in [zabbix] section, ensure zabbix_sender is reachable |
| Grafana Cloud 401/403 | Check token scope (needs MetricsPublisher role) in [grafana] section |
ModuleNotFoundError: cramjam |
Install with Grafana support: pip install speedtest-z[grafana] |
ModuleNotFoundError: opentelemetry |
Install with OTel support: pip install speedtest-z[otel] |
Copyright 2026 AIKAWA Shigechika

