Continuous broadband speed testing with your Raspberry Pi

Raspberry Pi3

Like many other people, I have a couple of Raspberry Pi’s lying around the house. One is dedicated as a music player, but there’s another one that didn’t have a specific purpose yet. Until now.

A few weeks ago, I complained on Twitter about a dodgy internet speed. This is quite common in Australia, because broadband speeds suck. My internet provider (iiNet) replied by asking me if I’d checked the connection using a wired connection to the ADSL modem. Well, of course I hadn’t, because I always use WiFi. Most people do, I reckon. I get their point, though. The connection might be dodgy because of the WiFi; nowadays you can find at least 5 or 6 different WiFi Access Points in any residential area competing for “air space”. Still, that question kinda shut down the exchange, because I didn’t have a reply (snarky or otherwise).

It got me thinking, though. I could connect my spare Raspberry Pi3 to my ADSL modem using Ethernet in stead of WiFi, install some sort of speed test module, and continuously monitor my internet speeds and ping times. When I say “continuously”, I mean around 6 times a day, but slightly randomised. I don’t want to hog my connection running speed tests only… Also, a speed test consumes data. Not a problem for me, because my ISP offers “unlimited” data, but I was thinking of the bigger picture. Maybe, just maybe, someone else might be interested too… If you’re still reading, you might be one of those people.

I started off by creating an NPM module called pi-speedtest. It uses the speedtest-net module from (by Ookla). Then I created a back-end using serverless technology and a front-end using React. If you’re interested in the tool, here’s how to use it.

First, go to the web app: Log in using GitHub (at the moment this is the only way to log in, because I feel most Raspberry Pi enthusiasts will have a GitHub account). On the account page, create a new access token that is needed by the NPM module. Click on the button “What is this?”, then on “Regenerate”. This will create a unique access token for you. Use the “Copy” button to copy the entire string verbatim so you can create the config file that the NPM module needs.

On your Pi, make sure you have node installed. Install the package using npm install -g pi-speedtest, which will install the module globally (you may need to prepend sudo to get it to work, it depends on your specific setup). Then create a file called config in the subdirectory ~/.st/ (meaning it is inside your home directory) and paste into it the contents you just copied from the webpage. You’ll almost certainly have to create the subdirectory:

$ cd
$ mkdir .st/

The config file should look something like this (everything must be on a single line):

token: 5f598b0a6717ac43df0d13340ac943a4fcd3992c28f435421d6fd442c6fd448b

Your specific token will, of course, be totally different.

You also need to make sure you install the command at:

sudo apt install at

because the module pi-speedtest uses it to schedule the next measurement.

When you’ve done all that, you can run your first measurement:

pi-speedtest test -V

The command test means it will run a test right away, and the option -V means it will show the results. The module is designed to be as quiet as possible, which is why you need to supply this option if you want to see the results. The results will, however, be uploaded to the servers regardless of this option. It takes a short while to run the test, but afterwards you will see the results. It will look something like this:

Run test
"speeds": {
"download": 8.374,
"upload": 0.42,
"originalDownload": 922234,
"originalUpload": 46122
"client": {
"ip": "",
"lat": -32.0753,
"lon": 115.8414,
"isp": "iiNet",
"isprating": 3,
"rating": 0,
"ispdlavg": 8.738,
"ispulavg": 1.561
"server": {
"host": "",
"lat": -31.9554,
"lon": 115.8585,
"location": "Perth",
"country": "Australia",
"cc": "AU",
"sponsor": "Telstra",
"distance": 13.43,
"distanceMi": 8.34,
"ping": 70.4,
"id": "2627"

It will show you a bunch of fields that have been returned by the Ookla module.

After running your first test, you should be able to see the results in the web app. Go to either Charts or to Connection to see the results. The charts will be rather sparse giving you only have a single sample, but you’ll see something.

Download speed chart

If you want to do continuous measurements, run the following command:

pi-speedtest start -V

This will schedule a measurement some time in the future. The next measurement will on average be 4 hours into the future, but there is some variability built in to prevent from measuring at roughly the same times every day. You can use the option -r if you also want to run an immediate test.

Stopping the measurement is as simple as running this command:

pi-speedtest stop -V

This will remove the next scheduled measurement. I haven’t implemented a ‘status’ command, but you can see whether a measurement is scheduled by running atq:

$ atq
93 Tue Apr 3 16:45:00 2018 a sander

If you don’t use at for any other purpose, then this will show you the next measurement. You can also check the job number, which is stored in ~/.st/job. It should match the first number of the output of atq.

The not so fine print

No warranty Feel free to use the tools I built to measure your own ISP speeds. However, I can’t give you any warranty whatsoever.

About GitHub We only request access to the scope user:email, so there’s nothing we can do with your GitHub account apart from reading some public fields. This is by design. We store the GitHub access token in a database table, but it is encrypted.

About data The measurement data that is stored in the database is extremely limited, not even your IP address is stored. The only data we store are upload and download speeds, ping time, ISP name, server ID (of the server against which the speed test was ran), and city, country, and country code.

Data usage Also, be aware that speed tests use data. I’m not sure how much, but I’ve seen figures of around 5–10MB (also depends on whether your ISP counts uploaded data separately). If you run 6 measurements a day for 30 days, you’ll have used up 10 x 6 x 30 = 1,800 MB. That’s quite a lot of data just for measuring your ISP speed. No problem if you have an unlimited data allowance like I have, but quite prohibitive if you’re using a connection with a very limited data allowance. So be careful!

Using cron If you don’t want to use the automatic testing the module offers out of the box, you could always set up a daily cron job in order to run the manual test. That will significantly reduce your data usage.

Linux too You can run the test on any system that supports node. Maybe you have a Linux server connected to your broadband modem. You can install the module on your server, in that case. It’s up to you.

30 Day window Finally, at the moment, the server discards all samples that are older than 30 days. I don’t see much point in keeping the data for much longer.

It’s a Beta The current version is very much a Beta version. It’s a simple tool that does what it needs to do, but without any frills. If you have any ideas you’d like to see implemented, please hit me up. I can’t guarantee it will ever be built, because I can only spend limited time on it.

Have fun!