How to Monitor Internet Speed on Raspberry Pi (CLI & Python)
Dealing with slow Internet speeds can be frustrating. As a sysadmin, I needed to ensure we always had fast and reliable Wi-Fi. I used a Raspberry Pi to test and monitor internet speed regularly. In this article, I’ll show you how you can do the same to keep an eye on your Internet connection.
SpeedTest is probably the most popular website for testing Internet connection performance. A CLI software available for Linux that can be used in scripts to automatically check Internet speed. Results can be stored in a database and displayed as needed.
In this tutorial, I’ll show you how to install SpeedTest on your Raspberry Pi, run tests manually, or automate everything, and even build a web dashboard with your Internet speed history.
If you’re looking to quickly progress on Raspberry Pi, you can check out my e-book here. It’s a 30-day challenge where you learn one new thing every day until you become a Raspberry Pi expert. The first third of the book teaches you the basics, but the following chapters include projects you can try on your own.
How to Perform Speed Tests on Raspberry Pi
If you want to run a command to check your current Internet speed occasionally, you can keep things pretty simple. Let’s start with that.
Introducing SpeedTest & SpeedTest CLI
SpeedTest.net is a cool website where you can quickly check your Internet speed. It’s free to use, but it’s mostly built for end-users, with a desktop environment and web browser.
They also offer options for developers, with a CLI version. CLI stands for “Command Line Interface”, and once SpeedTest CLI is installed, you can run the test by typing a simple command line. This is perfect if you have a Raspberry Pi on your network or don’t want to use a web browser every time.
In this first section of the tutorial, I’ll show you how to install it on your Raspberry Pi (but it works the same on most Linux servers), and run tests with command lines.
Installing SpeedTest on Raspberry Pi
The Raspberry Pi OS default repository has a SpeedTest package, but according to my tests, it doesn’t work. I guess it’s an outdated version that is no longer compatible with the current servers.
So follow these steps to install it instead:
- Make sure CURL is installed on your system:
sudo apt install curl
- Download and run the installation script:
curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | sudo bash
- You can then use APT to install it:
sudo apt-get install speedtest
That’s it, the “speedtest” command is now installed and ready to use.
Are you a bit lost in the Linux command line? Check this article first for the most important commands to remember and a free downloadable cheat sheet so you can have the commands at your fingertips.
First test with SpeedTest CLI
Using SpeedTest in the command line is straightforward. Type this command in a terminal:speedtest
On the first run, accept the license, type YES and enter twice to start the test. You won’t need to do it again after that.
Also: Probably one of the best Raspberry Pi workstations (review)
It's a free PDF guide containing every Raspberry Pi Linux command you should know!
Download now
After a few seconds, the Internet speed will be shown in your terminal directly:
SpeedTest shows the speed of download and upload, as well as the ping. It also shows details such as average, low and high jitter and any packet loss. You’re probably most interested in the Download and Upload values in Mbps, but you can check the other values if needed.
Key options of SpeedTest CLI
The default result is usually sufficient for a quick check, but if you need more control over the test or the result format, SpeedTest CLI comes with many advanced options.
Here is a summary of the most useful ones:
- Show the help:
speedtest -h
- List nearest servers:
speedtest -L
- Use a specific server for the test:
speedtest -s <server_id>
- Specify the network interface:
speedtest -I <interface>
- Change output format:
speedtest -f <format>
We’ll use that later, as it can be changed to CSV or JSON instead of the default human-readable format. For example:speedtest -f json
- Change units:
speedtest -u <unit>
For example:speedtest -u Mibps
It only works with the default output format (human-readable).
You can combine multiple options to get exactly what you want.
For most of you, this should be enough to run quick tests when you feel the Internet is slow. You can get the result quickly and investigate from there if needed. But stay with me if you want to go a bit further, automate these tests and analyze them later from a web interface.
It's a free PDF guide containing every Raspberry Pi Linux command you should know!
Download now
Automated tests with SpeedTest and Python
Project Overview
The end goal with this project is to have your internet speed tested at regular intervals (be it 5 minutes, 15 minutes, an hour, etc.) and to have a way to check the results when you need it (maybe you do it daily, weekly or just when you feel the internet is slow, it doesn’t matter).
I’ll try to keep things as simple as possible so that anyone can follow the instructions, but to give you an idea of what to expect, here are the main steps:
- Write a Python script that executes the SpeedTest command and stores the results.
- Automate this script to run at regular intervals.
- Have a way to check results, whether manually or via a web page.
Then, depending on your Python level, it’s up to you to do the minimum or go way beyond by improving this to get exactly what you want.
Requirements
I know there are many libraries and methods we could use to do that, but as mentioned, trying to keep things simple, the only package you need at this point is SQLite:sudo apt install sqlite3
That’s the database I’ll use to save the test results, so we can check them whenever we want after the tests (manually or via a script or page).
If you’re new to Python, I strongly recommend you familiarize yourself with the basic syntax before reading on, as I won’t necessarily explain everything here. You can check out my beginner’s guide here, or better yet, download my book “Master Python on Raspberry Pi“ to quickly become a pro, whatever your current level.
Writing the Python script
I have found a few SpeedTest libraries, but most seem outdated, so I prefer using the Linux command directly (via a subprocess). I’m sure this will still work in a few years when you read this.
So basically, my script runs the Linux command, waits for the test results, gets them in JSON format, and stores them in a SQLite table. Here’s the whole script:
import subprocess import json import sqlite3 from datetime import datetime # Run the Speedtest CLI command and get the result in JSON format def run_speedtest(): result = subprocess.run(['speedtest', '--format', 'json'], capture_output=True, text=True) return json.loads(result.stdout) # Store the results in the SQLite database def save_results(data): conn = sqlite3.connect('speedtest_results.db') cursor = conn.cursor() # Create table if not exists cursor.execute('''CREATE TABLE IF NOT EXISTS results (timestamp TEXT, download REAL, upload REAL, ping REAL)''') # Insert results cursor.execute('INSERT INTO results (timestamp, download, upload, ping) VALUES (?, ?, ?, ?)', (datetime.now().isoformat(), data['download']['bandwidth'] / 1e6, # Convert to Mbps data['upload']['bandwidth'] / 1e6, data['ping']['latency'])) conn.commit() conn.close() speedtest_data = run_speedtest() save_results(speedtest_data)
The first function creates a subprocess to execute the command, the second is used to store the results in the database, and I call these two functions in a row each time we run the script. As mentioned, nothing fancy here.
You can use Nano or any of your favorite text editors, copy/paste the code in it, and run it once with:python3 <script_name>
For example:python3 speed_test.py
The test will take a few seconds to complete. After that, a new file named “speedtest_results.db” will be created in your current folder. This is your database with the history of all previous tests (I’ll show you how to read it later).
Automating tests with a Cron
Running this script manually is of little interest compared to running it from the command line. The point of having a script is to schedule it to run automatically, at regular intervals.
On Linux, scheduled tasks are managed by adding a new line in the crontab file. Here is how to do it:
- From a terminal, open the crontab with:
crontab -e
- If it’s your first time here, you might need to confirm which editor you want to use (press ENTER to keep the default).
- Scroll to the bottom of the file, and add a line following this format:
<minute> <hour> <day_of_month> <month> <day_of_week> <command>
So typically, to run your script every 15 minutes, you can do something like:*/15 * * * * /usr/bin/python3 speed_test.py
If you arne’t familiar with this syntax, you can use a Crontab generator tool to create the syntax for you. - Save and exit (CTRL+O, Enter and CTRL+W if you use Nano).
From there, your Python script should run automatically as scheduled, and save the results each time in your database.
Note: My example works if everything is in the home folder (script and database), you may have to tweak the crontab or script a bit if you want to keep everything in a different path.
Also: 15 Easy Projects for Raspberry Pi Beginners
It's a free PDF guide containing every Raspberry Pi Linux command you should know!
Download now
It's a free PDF guide containing every Raspberry Pi Linux command you should know!
Download now
Reminder: Remember that all the members of my community get access to this website without ads, exclusive courses and much more. You can become part of this community for as little as $5 per month & get all the benefits immediately.
Analyzing tests results
Now that our Internet speed test is scripted and automated, let’s see how to review the results. I’ll also give you instructions on creating a web page that lists the history results or even displays them on a graph if you want, but let’s start simple.
Reading results history from the database
SQLite is very convenient for this kind of project. There is no server and no complicated setup, it just stores the values in a file, and we can read it when we need. It’s almost like a CSV file.
But we still need to use a specific command and a simple query to get the results we want, here is how to access them:
- Open the database with:
sqlite3 speedtest_results.db
Again, I guess you kept the name I used and are in the right folder, adjust the command accordingly if needed. - You now have a prompt to type commands and queries for SQLite, try this:
SELECT * FROM results;
It will give you all the results stored in your database, in a raw format: - It’s not perfect, but it allows you to see everything quickly.
As a reminder, the first column is the test date, followed by download, upload and ping. You can choose to display the columns’ names with:.headers on
- You can customize the query to get exactly what you want.
For example, to see the download speed on the last 5 results:SELECT timestamp,download FROM results ORDER BY timestamp DESC LIMIT 5;
Check the SQLite documentation for more details. - To exit the SQLite prompt, type:
.exit
and press Enter.
Not bad, right? From there, you can use this database with any language or tool you’re familiar with. I’ll take it further and show you how to create a web page in Python, but do what’s easiest for you (or stop here if you don’t need more!).
Creating a simple web page
One easy way to create a web page with Python is by using the Flask library. You can install it with PIP in a virtual environment, or simply as a package:sudo apt install python3-flask
Once installed, you need to create an HTML template for your page, and a Python script to get the data and fill it into your template.
I’ll give you the code to create a minimal web page, but feel free to improve it from there.
Create your first HTML template
The first step when creating a page for a Flask server, is to create the template using HTML code only.
Start by creating a new subfolder, named “templates”:mkdir templates
Create a new file in it, for example:nano templates/table.html
Copy/paste this code into it:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Speedtest Results</title> <style> table { border-collapse: collapse; width: 100%; } table, th, td { border: 1px solid black; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> </head> <body> <h1>Internet Speed Test Results</h1> <table> <thead> <tr> <th>Timestamp</th> <th>Download Speed (Mbps)</th> <th>Upload Speed (Mbps)</th> <th>Ping (ms)</th> </tr> </thead> <tbody> {% for row in results %} <tr> <td>{{ row[0] }}</td> <td>{{ row[1] }}</td> <td>{{ row[2] }}</td> <td>{{ row[3] }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
Create your Python script
We can use this template in a Python script, to start a web server, and tell it where to get the data to fill the HTML page.
Create a new Python script, for example:nano web.py
Here’s the full Python code you can copy/paste:
from flask import Flask, render_template import sqlite3 app = Flask(__name__) def get_data(): # Connect to the SQLite database conn = sqlite3.connect('speedtest_results.db') cursor = conn.cursor() # Query the database cursor.execute("SELECT * FROM results") rows = cursor.fetchall() # Close the connection conn.close() return rows @app.route('/') def index(): # Get the data from the database data = get_data() # Render the HTML template and pass the data return render_template('table.html', results=data) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)
The get_data() function opens the SQLite database and runs the query we have seen earlier. Then we start a web server on port 5000 to answer HTTP requests. You’ll understand everything once you run this script.
Save and exit Nano.
Try it!
With the two files ready, you can now start the server with:python3 web.py
You’ll see the URL in your terminal, you can even click on it. In your web browser, you should get something like that with your values:
That’s the bare minimum, you can play a bit from there, changing the style, columns, and order. Maybe you can only show the last 24H, add the average/worse/best values, etc.
You can even use Matplotlib or an alternative to draw a chart with your Internet speed history.
If you are interested in this topic and have additional questions, jump into the community forums and ask for help or share your results.
Whenever you’re ready, here are other ways I can help you:
The RaspberryTips Community: If you want to hang out with me and other Raspberry Pi fans, you can join the community. I share exclusive tutorials and behind-the-scenes content there. Premium members can also visit the website without ads.
Master your Raspberry Pi in 30 days: If you are looking for the best tips to become an expert on Raspberry Pi, this book is for you. Learn useful Linux skills and practice multiple projects with step-by-step guides.
The Raspberry Pi Bootcamp: Understand everything about the Raspberry Pi, stop searching for help all the time, and finally enjoy completing your projects.
Master Python on Raspberry Pi: Create, understand, and improve any Python script for your Raspberry Pi. Learn the essentials step-by-step without losing time understanding useless concepts.
You can also find all my recommendations for tools and hardware on this page.