Skip to content

Instantly share code, notes, and snippets.

@gmemstr
Last active February 10, 2026 14:32
Show Gist options
  • Select an option

  • Save gmemstr/9790ddba9a2133a9e7a4791cb622acc8 to your computer and use it in GitHub Desktop.

Select an option

Save gmemstr/9790ddba9a2133a9e7a4791cb622acc8 to your computer and use it in GitHub Desktop.
Speedtest against Hetzner servers

hetz-speedtest

small python for basic speed testing again public hetzner endpoints. provides a rough estimate of latency to datacenters as well.

usage

pipenv install
pipenv shell
python hetz-speedtest.py [lg|md|sm]
# Alternatively
pipenv run python hetz-speedtest.py [lg|md|sm]
arg size
lg 10GB
md 1GB
sm 100MB
import sys
import time
import requests
import math
import subprocess
import platform
hosts = {
"fsn1-speed.hetzner.com": {
"sm": "https://fsn1-speed.hetzner.com/100MB.bin",
"md": "https://fsn1-speed.hetzner.com/1GB.bin",
"lg": "https://fsn1-speed.hetzner.com/10GB.bin",
},
"hel1-speed.hetzner.com": {
"sm": "https://hel1-speed.hetzner.com/100MB.bin",
"md": "https://hel1-speed.hetzner.com/1GB.bin",
"lg": "https://hel1-speed.hetzner.com/10GB.bin",
},
"speed.hetzner.de": {
"sm": "https://speed.hetzner.de/100MB.bin",
"md": "https://speed.hetzner.de/1GB.bin",
"lg": "https://speed.hetzner.de/10GB.bin",
},
"ash.icmp.hetzner.com": {
"sm": "http://ash.icmp.hetzner.com/100MB.bin",
"md": "http://ash.icmp.hetzner.com/1GB.bin",
"lg": "http://ash.icmp.hetzner.com/10GB.bin",
},
"hil.icmp.hetzner.com": {
"sm": "http://hil.icmp.hetzner.com/100MB.bin",
"md": "http://hil.icmp.hetzner.com/1GB.bin",
"lg": "http://hil.icmp.hetzner.com/10GB.bin",
}
}
def downloadFile(url):
points = []
with open("/dev/null", 'wb') as f:
start = time.process_time()
r = requests.get(url, stream=True)
total_length = int(r.headers.get('content-length'))
dl = 0
if total_length is None: # no content length header
f.write(r.content)
else:
for chunk in r.iter_content(1024):
dl += len(chunk)
f.write(chunk)
point = dl//(time.process_time() - start)
points.append(point)
avg = round(sum(points)/len(points), 2)
return avg
# get latency of host
def get_latency(host):
if platform.system() == "Windows":
return 0
try:
output = subprocess.check_output(["ping", "-c", "1", host])
output = output.decode("utf-8")
output = output.split("\n")
for line in output:
if "time=" in line:
return float(line.split("time=")[1].split(" ")[0])
except:
return 0
def convert_size(size_bytes: int) -> str:
if size_bytes == 0:
return "0B"
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return f"{s}{size_name[i]}"
# convert size to bits per second
def convert_speed(size_bytes: int) -> int:
return size_bytes * 8
def main() :
size = sys.argv[1]
for host in hosts:
file = hosts[host][size]
print(f"Downloading {file} from {host}")
(avg_speed) = downloadFile(file)
print(f"Average speed: {convert_size(avg_speed)}/s")
if platform.system() == "Windows":
print("Can't measure latency on Windows")
continue
print(f"Latency: {get_latency(host)}ms")
if __name__ == "__main__" :
main()
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
requests = "*"
[dev-packages]
[requires]
python_version = "3.8"
@Sleepful
Copy link
Copy Markdown

Easy terminal version:

for dc in sin nbg1 fsn1 hel1 ash hil; do echo "${dc}: $(ping -i .1 -c 10 -q "${dc}-speed.hetzner.com" | awk -F/ '/^round|^rtt/{print $5}')"; done | sort -n -k2

Copy link
Copy Markdown

ghost commented Feb 10, 2026

well that's just latency

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment