DEV Community

Cover image for Open Source Python CLI Internet Speed Test with Ping, Upload, Download & IP
Bijay Singh deo
Bijay Singh deo

Posted on

Open Source Python CLI Internet Speed Test with Ping, Upload, Download & IP

A few days ago, I had a simple idea:

What if I could type internetspeed in the terminal, press Enter, and instantly see my internet speed and public IP?

That tiny thought turned into a real project, a GitHub repository, an installable Python CLI, and eventually a PyPI package that anyone can install with:

pip install internetspeed
Enter fullscreen mode Exit fullscreen mode

Git Repo: https://github.com/cranky420/internetspeedtest.git

This post is about how I built it, what broke along the way, why open source matters, and what I learned from turning a local Python script into a real distributable tool.

Why I started this

I wanted something that felt as natural as Linux commands like:

date
pwd
ls
Enter fullscreen mode Exit fullscreen mode

I started with a local Python script that did three things:

  1. fetched my public IP
  2. measured download speed
  3. measured upload speed

The first version wasn’t elegant. It was just about proving the idea.

I used requests to fetch the public IP from a public API, then used a test function to measure network throughput.

That gave me the first “it works” moment.

And that matters a lot. In open source, people often jump too quickly to packaging, publishing, branding, and documentation. But the real first step is always the same:

Make one small thing work.

Turning a script into a CLI

!Image description(https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlk6vhoms7cb6xlh2h2d.png)

That sounds small, but it changes everything.

A real CLI feels like software.
A script feels like a file.

My project started to look more like a proper CLI application instead of a personal script.

Here is the general shape of the command:

import click
from rich import print
from speed import test_speed
Enter fullscreen mode Exit fullscreen mode

And then the command itself:

@click.command()
def cli():
    print("[cyan]Running internet test...[/cyan]")
    result = test_speed()

    print()
    print(f"[green]Download:[/green] {result['download']} Mbps")
    print(f"[green]Upload:[/green] {result['upload']} Mbps")
    print(f"[green]IP:[/green] {result['ip']}")
Enter fullscreen mode Exit fullscreen mode

That’s when it started feeling real.

The folder structure that made it clean

I began with a messy folder, like many first projects do. But once I wanted to publish it, I needed a cleaner structure.

My repo eventually looked like this:

internetspeedtest/
├── cli.py
├── speed.py
├── setup.py
├── README.md
├── requirements.txt
├── LICENSE
├── CONTRIBUTING.md
├── .gitignore
└── venv/

How the package became installable

The real transformation happened when I made the project installable as a command-line tool.

That meant adding setup.py and defining a console entry point.

Here is the essential idea:

from setuptools import setup

This tells Python packaging:

  1. the project name is internetspeed
  2. it has dependencies
  3. and the terminal command should be internetspeed

After installing the package in editable mode:

pip install -e .

I could run:

internetspeed

That was a huge milestone.

It meant the project was no longer just code in a folder. It was software with an interface.

I learned about:

  • API tokens
  • twine
  • trusted publishing
  • package naming
  • distribution builds
  • GitHub Actions workflows

At first, I got 403 errors. Later, I realized it was just a credential flow issue.

That kind of debugging is part of open source too. A project becomes real when you learn how to ship it, not just how to write it.

Publishing to PyPI

This was the moment the project became global.

Once the package was built properly, I could upload it to PyPI and make it available to anyone.

That means anyone can now do:

pip install internetspeed
Enter fullscreen mode Exit fullscreen mode

and then:

internetspeed
Enter fullscreen mode Exit fullscreen mode

That’s a massive shift.

A local repo became a public tool.

That is one of the most satisfying parts of software development: turning something personal into something shareable.

Why open source matters here

I did not want this to be a closed personal tool.

I wanted it to be open source because open source turns software into a conversation.

Once a repo is public, other people can:

  • inspect the code
  • report bugs
  • suggest improvements
  • add features
  • fix packaging
  • improve documentation
  • adapt it for their own workflow

That is powerful.

What I added to make it contributor-friendly

If you want other people to help, you need to make the project welcoming.

That means adding things like:

README.md

This explains what the project does, how to install it, and how to use it.

CONTRIBUTING.md

This tells people how to participate.

Clean Git history

Small, clear commits are easier to review and understand.

Open source does not start with “welcome contributors.”
It starts with making the project readable.

What internetspeed actually solves

At first glance, this may look like a tiny utility. But it solves a real workflow problem.

Sometimes you want to check:

  • your download speed
  • your upload speed
  • your public IP
  • whether a connection is behaving correctly

What I actually learned was this:

Open source is not just code. It is packaging, documentation, publishing, maintenance, debugging, and community design.

That was the biggest lesson.

A project becomes open source only when someone else can realistically use it, understand it, and contribute to it.

The long-term vision is to make it easy for anyone to check and observe their network speed from the terminal, and maybe even use it as part of a larger monitoring workflow.

Top comments (0)