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.1.tar.gz (16.5 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.1-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cfspeed-1.0.1.tar.gz
  • Upload date:
  • Size: 16.5 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.1.tar.gz
Algorithm Hash digest
SHA256 ba6271a1114419ff20a1c7298e34beab46c5db0901ee3fab71ba361bc241aa94
MD5 769673bf8ddfa27b01a3eae14954e229
BLAKE2b-256 779c4d083c11135b10531ba43efc132b3e18acaf8e635da546006f3e6e5f9a16

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cfspeed-1.0.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d411e4d15edffe0d86cb19905c316b3c564471fb1560c5546b54038c2b0c8a0d
MD5 c6e2ac5aaec806329ca59ae089637b41
BLAKE2b-256 ebf233dfa15c1f7e770a76328a059e2cdb3497b79087f340b1c29300bb3f470b

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