DEV Community

Cover image for Speedtest.net on Python!
Ali Sherief
Ali Sherief

Posted on

Speedtest.net on Python!

Most of you are probably familiar with https://speedtest.net, a website that measures the speed of your internet connection and reports your download, upload and ping speeds.

Did you know that Speedtest made a Python module for it? It is called speedtest-cli, and it's a little old but still works admirably well. I'm going to show you how to use it to measure your network speed from within Python?

What if I told you that this speedtest-cli module powers the speedtest-cli command line program as well? The one referenced in their announcement. It may even be powering the main speedtest.net site as well.

So by understanding how this program works, you gain the enormous potential of making something scalable using speedtest.net services.

Why measure within Python?

There are some advantages to running a speedtest using an API vs. a shell command.

  • You can easily parse the output and errors
  • No informational output is printed to standard error
  • It is easier to pass arguments to an API call than a shell script called from a Python program.

So let's see how this speedtest-cli thing works, shall we?

The API calls

Installation is dead simple; you just run pip install speedtest-cli. This doesn't need it's own section.

Note: installing the speedtest-cli module also installs the speedtest-cli command line program.

Getting a list of servers



import speedtest

s = speedtest.Speedtest()
servers = s.get_servers()


Enter fullscreen mode Exit fullscreen mode

This returns 49 speedtest.net servers for now, this number will go up or down depending on if speedtest.net creates and deletes servers, which are hosted by ISPs at their datacenters. The result is a dictionary of servers categorized by distance. In other words, the distances are the dictionary keys, and they are floating-point numbers. The best way to iterate through this structure therefore is using [*s.get_servers().values()].



s.get_best_server()


Enter fullscreen mode Exit fullscreen mode

Returns the nearest server, the one with the smallest distance.



s.download(threads=None)
s.upload(threads=None, pre_allocate=True)


Enter fullscreen mode Exit fullscreen mode

These two functions perform the download and upload tests respectively and return similar structures. The threads keyword argument takes a number that determines the number of threads to use for the test. By default it is None, which means the speedtest.net server decides how many threads to use.

If pre_allocate=True (upload() only), then the entire upload data is stored in memory before running the test. This improves the upload performance and thus result somewhat, but it might cause you to run out of memory on small-memory systems, so you can set it to False to disable that, and store the upload data piece by piece.

s.results.share()

Makes an HTTP POST request to speedtest.net with your results and returns a link to an image of your results, such as this:

speedtest results as image

Thanks for reading

If you see any errors in this post, please let me know so I can correct them.

Top comments (4)

Collapse
 
myavuzyagis profile image
M.Yavuz Yagis

836mbps?😳

Collapse
 
zenulabidin profile image
Ali Sherief

This is a test server I rented from Leaseweb for the purposes of this article.

Collapse
 
snlgrg profile image
ѕυηιℓ gαяg

Hey, Nice Article.
one other thing I was expecting from this was that how speedtest works internally. How the speed of the internet is measured. It would be great if you could add that part also here

Collapse
 
zenulabidin profile image
Ali Sherief

From my observations in the speedtest-cli code, it appears that each major data center is hosting the server-side part where speedtest-cli uploads to and downloads from as part as those tests. It also collects the upload, download speeds, latency of the connection and also naming information about the data center itself.

But here is the most important part: The upload and download tests are sending chunks of data in an interval. Sequences of repeated0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ strings. The size of each chunk is about 10KB. It's probably to give speedtest a more uniform measurement of how fast that chunk size gets through, as opposed to sending strings of different sizes.

Here is where the chunk data is assembled. Then it's put in a GET or PUT request depending on the test. The function name is a misnomer: It doesn't actually read anything from a file even though it's called for both upload and download tests.