Skip to main content

📦 Speedkit

Python Versions PyPI License

Python SDK for network speed testing

Measures download, upload, and latency with the official Ookla Speedtest CLI and falls back to LibreSpeed when Speedtest is blocked or unavailable.

Features

  • Zero setup — Ookla Speedtest first, LibreSpeed when it is blocked or fails.
  • Automatic binaries — downloaded and cached for your OS on first run.
  • Nearby servers — the lowest-latency server is picked automatically.
  • Self-recovery — failed attempts are retried, broken servers excluded.
  • Uniform results — same fields and units whichever provider ran; client info from geo-IP.

Installation

pip install speedkit

Usage

from speedkit import Speedkit

kit = Speedkit()
result = kit.run()

print(f"download: {result.download / 1_000_000:.1f} Mbit/s")
print(f"upload:   {result.upload / 1_000_000:.1f} Mbit/s")
print(f"ping:     {result.ping:.1f} ms")

data = result.to_dict()  # plain JSON-serializable dict

Or from the command line:

speedkit                  # auto: Ookla, then LibreSpeed
speedkit -p librespeed    # pin one provider
speedkit -t 180           # time budget per provider in seconds
speedkit -a 1             # disable retries
speedkit --no-geoip       # no third-party geo-IP request

Speedkit() needs no configuration; everything it accepts:

kit = Speedkit(
    provider="auto",   # "auto" | "ookla" | "librespeed" — a pinned provider never falls back
    timeout=120,       # time budget per provider in seconds, covering all attempts
    attempts=2,        # measurement attempts within the budget; 1 disables retries
    lookup_geoip=True, # resolve client info from a geo-IP service; False makes no such request
    cache_dir=None,    # where CLI binaries are cached; None = user cache directory
)

Result format

SpeedtestResult.to_dict() returns download/upload in bits per second and ping in milliseconds:

{
  "client": {
    "ip": "203.0.113.7",
    "isp": "Example ISP",
    "country": "ZZ",
    "city": "Springfield"
  },
  "server": {
    "name": "Springfield",
    "country": "Freedonia",
    "sponsor": "Example Sponsor",
    "id": "1234",
    "host": "speedtest.example.net:8080",
    "latency": 0.681
  },
  "provider": "ookla",
  "download": 293111520.0,
  "upload": 292265640.0,
  "ping": 0.681,
  "timestamp": "2026-07-19T15:22:48Z",
  "bytes_sent": 418465064,
  "bytes_received": 426981996
}
  • client — from a geo-IP service, identical whichever provider measured.
  • server — the test server that provider picked; unreported fields stay at "" / 0.0.
  • provider — which measurer produced the result.

Geo-IP lookup

Client details come from the first service that answers: ipinfo.io → ipwho.is.

  • The lookup takes a fraction of a second.
  • If every service is unreachable, the measurement is still returned — with whatever client info the CLI reported.

This sends your IP address to the geo-IP service that answers.

Pass lookup_geoip=False (or --no-geoip) to skip it entirely. Nothing is then sent to a third party, and client keeps what the measuring CLI itself reported — ip and isp from Ookla, plus country from LibreSpeed. Fields neither reports, city above all, stay at "", so client is no longer identical across providers.

Binaries

Provider Version Platforms
Ookla Speedtest CLI 1.2.0 Linux x86_64/aarch64, macOS
librespeed-cli 1.0.13 Linux x86_64/aarch64, macOS

Binaries are downloaded on first use and cached per platform:

  • Linux — ~/.cache/speedkit
  • macOS — ~/Library/Caches/speedkit

Every archive is checked against a SHA-256 digest pinned in speedkit/binaries.py before anything is extracted or made executable. A release asset that changed after it was pinned raises BinaryDownloadError instead of running. All network access is HTTPS with certificate verification; plain HTTP, and any redirect leaving TLS, is refused.

Set SPEEDKIT_OOKLA_BINARY / SPEEDKIT_LIBRESPEED_BINARY to a path of a preinstalled binary to skip downloading entirely — useful for offline machines and locked-down networks. A path that is missing or not executable is refused by name; anything runnable is executed as given and bypasses the checksum, so it is on you to trust it.

To pre-download the binaries at image build time (Docker, CI):

python -c "from speedkit.binaries import ookla_binary, librespeed_binary; ookla_binary(); librespeed_binary()"

Running the Ookla provider passes --accept-license --accept-gdpr, which implies acceptance of the Ookla EULA and privacy terms.

Errors

Every error derives from SpeedkitError and carries an actionable hint:

from speedkit import Speedkit, SpeedkitError

try:
    result = Speedkit().run()
except SpeedkitError as error:
    print(error)  # cause, and a hint on how to fix it

UnsupportedPlatformError — no prebuilt binary for this OS/arch; BinaryDownloadError — the binary could not be fetched; SpeedtestError — the measurement itself failed.

License

This repository is distributed under the MIT License.

Metadata

Release files for speedkit 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for speedkit 0.2.2
File Size Uploaded Provenance
speedkit-0.2.2.tar.gz 25.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for speedkit 0.2.2
File Interpreter ABI Platform
speedkit-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 44.9 kB

Release files / speedkit-0.2.2.tar.gz

Download URL speedkit-0.2.2.tar.gz
Size 25.6 kB
Tags Source
SHA-256 checksum
How to use checksums
429533c62100ddf519d0fb64201b611931dd7e5fe943718dd35eef32d4b1ceb6
BLAKE2b-256 checksum
How to use checksums
268150e91bdf24b032942de7c135471d5389ba281abbc901a04a94908e06c453
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / speedkit-0.2.2-py3-none-any.whl

Download URL speedkit-0.2.2-py3-none-any.whl
Size 19.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2df650633fda737d7b5a932a5cd9797c98b358a5b4db0d1cd1e5bd83515c4994
BLAKE2b-256 checksum
How to use checksums
b661e523c244a5d1b7940fd1a69e31802ca341c7a789b59aecd7ab92d976a66e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for speedkit 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page