Skip to main content

cfspeed

Cloudflare speed test library for Python.

pip install cfspeed


What is this?

cfspeed measures your connection to the nearest Cloudflare edge using Cloudflare's speed test endpoints (speed.cloudflare.com). It runs parallel HTTP streams for download and upload, measures idle and loaded latency, and outputs clean CLI results or JSON.

Zero core dependencies. SOCKS5 proxy support is optional.


Quick start

pip install cfspeed
import cfspeed

client = cfspeed.Client(parallel_streams=4)
result = client.run(timeout=30)
print(result)
print(result.json())

CLI

# Default run
cfspeed

# With custom options
cfspeed --parallel 8 --duration 5 --json

# JSON output piped to jq
cfspeed --json | jq .download_mbps

# Behind a proxy
cfspeed --proxy http://127.0.0.1:3128
cfspeed --proxy socks5://127.0.0.1:1080  # requires pip install cfspeed[socks5]

CLI flags:

Flag Short Default Description
--parallel -p 4 Number of parallel streams (1–64)
--duration -d 10 Measurement duration per phase (seconds)
--download-size -ds 10MiB Bytes per download stream
--upload-size -us 10MiB Bytes per upload stream
--http-timeout -t 30 Per-request timeout (seconds)
--proxy -x Proxy URL (http://..., socks5://...)
--insecure -k false Skip TLS verification
--json -j false Output as JSON

Python API

from cfspeed import Client, Result, parse_size

Client(**kwargs)

Keyword arguments map directly to configuration:

client = Client(
    parallel_streams=8,       # Stream concurrency (clamped 1–64)
    measure_duration_secs=10.0, # Per-phase duration
    latency_sample_count=20,  # Latency probe count
    download_payload_bytes=10_485_760,  # 10 MiB per stream
    upload_payload_bytes=10_485_760,    # 10 MiB per stream
    http_timeout_secs=30.0,   # Request timeout
    insecure=False,           # Skip TLS verification
    base_url="https://speed.cloudflare.com",
    proxy_url=None,           # http:// or socks5:// URL
)

client.run(timeout=None) -> Result

Full speed test — runs latency, discovery, download, and upload in sequence. Raises CfspeedError on failure.

result = client.run()

Individual phases

latency_ms, jitter_ms = client.run_latency()
mbps, loaded_lat_ms, total_bytes, failed_count = client.run_download()
mbps, loaded_lat_ms, total_bytes, failed_count = client.run_upload()

Result

A dataclass with all measurement fields:

result.download_mbps          # float
result.upload_mbps            # float
result.latency_ms             # float
result.jitter_ms              # float
result.loaded_latency_ms      # float — latency under download load
result.upload_loaded_latency_ms  # float — latency under upload load
result.colo                   # str — Cloudflare PoP code (e.g. "MNL")
result.server                 # str — server location
result.timestamp              # datetime (UTC)
result.download_bytes         # int
result.upload_bytes           # int
result.parallel_streams       # int
result.failed_streams         # int — streams that errored out

str(result)                   # ASCII table output
result.json()                 # pretty-printed JSON string

parse_size(size_str: str) -> int

Parse human-readable sizes. Raises ValueError on bad input.

parse_size("10MB")    # → 10_000_000
parse_size("1GiB")    # → 1_073_741_824
parse_size("500KB")   # → 500_000
parse_size("100 B")   # → 100

Cancellation

client.cancel()
client.is_cancelled   # → bool

Call cancel() from another thread or a signal handler (SIGINT) to stop an in-flight test. All phases check the flag before every HTTP call.

Proxy error detection

if client.proxy_error:
    print(f"warning: {client.proxy_error}")

Returns a description of proxy misconfiguration (missing scheme, unsupported protocol), or None.


How it works

1. Latency   → HEAD /__down?bytes=0       (×20 samples)   → median + MAD
2. Discovery → GET  /cdn-cgi/trace        (1 request)      → colo + location
3. Download  → GET  /__down?bytes=N       (parallel loop)  → Mbps + loaded latency
4. Upload    → POST /__up                 (parallel loop)  → Mbps + loaded latency

Download and upload run background HEAD probes every 500ms to measure loaded latency — how your connection behaves under traffic.

Endpoints

Endpoint Method Purpose
speed.cloudflare.com/__down?bytes=N GET Download N bytes of PRNG data
speed.cloudflare.com/__up POST Upload random data
speed.cloudflare.com/cdn-cgi/trace GET Identify colo (PoP) and location
speed.cloudflare.com/__down?bytes=0 HEAD Lightweight latency probe

Output examples

CLI

╔═══════════════════════════════════╗
║  Cloudflare Speed Test Result     ║
╠═══════════════════════════════════╣
║  Download:            24,545 Mbps ║
║  Upload:              24,649 Mbps ║
║  Latency:                0.04 ms  ║
║  Jitter:                 0.01 ms  ║
║  Loaded Lat:        0.16 / 0.29   ║
║  Server:      MNL                 ║
║  Colo:        MNL                 ║
║  Data:        19.5 GB (2 failed)  ║
╚═══════════════════════════════════╝

JSON

{
  "download_mbps": 24545.0,
  "upload_mbps": 24649.0,
  "latency_ms": 0.04,
  "jitter_ms": 0.01,
  "loaded_latency_ms": 0.16,
  "upload_loaded_latency_ms": 0.29,
  "colo": "MNL",
  "server": "MNL",
  "timestamp": "2026-07-28T14:51:46Z",
  "download_bytes": 4227486720,
  "upload_bytes": 5497500000,
  "parallel_streams": 4,
  "failed_streams": 2
}

Proxy support

HTTP / HTTPS

Works out of the box:

cfspeed --proxy http://127.0.0.1:3128
Client(proxy_url="http://127.0.0.1:3128")

SOCKS5

Requires the optional socks5 extra:

pip install cfspeed[socks5]
cfspeed --proxy socks5://127.0.0.1:1080
Client(proxy_url="socks5://127.0.0.1:1080")

Invalid proxy detection

If the proxy URL is malformed, the client surfaces a warning:

if client.proxy_error:
    print(f"warning: {client.proxy_error}")

Testing

pip install pytest
pytest tests/ -v    # 26 tests

Requirements

  • Python ≥ 3.10
  • Zero required dependencies
  • Optional: PySocks>=1.7.1 for SOCKS5 proxy support

FAQ

Q: What does "loaded latency" mean? A: Latency measured while the connection is under download/upload load. The gap between idle and loaded latency tells you how bad your bufferbloat is.

Q: Can I use this behind a NAT or CGNAT? A: Yes. Cloudflare's test uses short-lived HTTP connections that work behind NAT.

Q: Do I need a Cloudflare account? A: No. The test hits public endpoints at speed.cloudflare.com.

Q: How is this different from speedtest-cli? A: cfspeed uses Cloudflare's own speed test infrastructure (the same one at speed.cloudflare.com), runs parallel HTTP streams, and measures loaded latency.


License

MIT © 2026 techroy23

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cfspeed-1.0.2.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cfspeed-1.0.2-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file cfspeed-1.0.2.tar.gz.

File metadata

  • Download URL: cfspeed-1.0.2.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for cfspeed-1.0.2.tar.gz
Algorithm Hash digest
SHA256 c065d642a007d00190f21e073e8d9cfa4896ab81427712bb03dd916216a700f3
MD5 b40fac1d76f54761a51f3adab7bbbd0c
BLAKE2b-256 b8b3543dbe91beede054e48a806f6e38db03ff1ae0812f948edbf179840bf252

See more details on using hashes here.

File details

Details for the file cfspeed-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: cfspeed-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for cfspeed-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 662378c44ee105d5bb0f5d92f6c43b4f19a48d6ff86631993ed420e82b11e37f
MD5 d392ebcc4253858e03f93a32098c25b8
BLAKE2b-256 a34a6da6f9f92187b35442ccdc48959411699219d00612d18aea02c976b4b831

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page