๐Ÿ“ถ Build a Local Network Speed-Test Tool

๐Ÿ“ถ Build a Local Network Speed-Test Tool

๐‰๐จ๐ข๐ง ๐œ๐จ๐ฆ๐ฆ๐ฎ๐ง๐ข๐ญ๐ฒ - ๐‚๐‹๐ˆ๐‚๐Š ๐‡๐„๐‘๐„

Want to know the actual speed between two devices on your Wi-Fi network instead of testing your Internet connection?

You can create your own simple speed-test website using Python + Flask. One device acts as the local server, while another device opens the webpage and measures download/upload speed.

For serious network benchmarking, tools such as iPerf3 are designed specifically for active bandwidth measurements.

This tutorial builds a browser-based version that is easy to understand and run on Android, Windows, Linux, or macOS.


๐Ÿงฐ What You Need

  • Android phone, PC, or laptop
  • Python
  • Flask
  • Two devices on the same Wi-Fi
  • Web browser

Example:

๐Ÿ“ฑ Phone
   โ†“
 Wi-Fi Router
   โ†“
๐Ÿ’ป Laptop

The server can run on either device.


1๏ธโƒฃ Install Python

If you're using Android with Termux:

Install Termux from:

https://github.com/termux/termux-app

Then run:

pkg update
pkg install python

Check:

python --version

On Windows/macOS/Linux, install Python from:

https://www.python.org/


2๏ธโƒฃ Create the Project

In Termux:

mkdir ~/speedtest
cd ~/speedtest

Create the application:

nano app.py

3๏ธโƒฃ Install Flask

Run:

pip install flask

Flask provides the web routes and request handling needed for our small local application. Its documentation also supports handling uploaded files through request.files, which is useful for the upload-speed test.


4๏ธโƒฃ Create the Speed-Test Server

Put this inside app.py:

from flask import Flask, request, Response, render_template_string
import time

app = Flask(__name__)

HTML = """
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Local Network Speed Test</title>

    <style>
        body {
            margin: 0;
            font-family: Arial, sans-serif;
            background: #101828;
            color: white;
        }

        .container {
            max-width: 650px;
            margin: auto;
            padding: 25px;
        }

        h1 {
            text-align: center;
        }

        .card {
            background: #1d2939;
            border-radius: 18px;
            padding: 25px;
            margin-top: 20px;
        }

        button {
            width: 100%;
            padding: 15px;
            margin-top: 12px;
            border: 0;
            border-radius: 10px;
            font-size: 17px;
            cursor: pointer;
        }

        .result {
            text-align: center;
            font-size: 32px;
            margin-top: 20px;
        }

        .small {
            color: #98a2b3;
            text-align: center;
        }
    </style>
</head>

<body>

<div class="container">

    <h1>๐Ÿ“ถ Local Speed Test</h1>

    <p class="small">
        Test the connection between two devices on your local network.
    </p>

    <div class="card">

        <h2>โฌ‡๏ธ Download</h2>

        <button onclick="downloadTest()">
            Start Download Test
        </button>

        <div id="download" class="result">โ€”</div>

    </div>

    <div class="card">

        <h2>โฌ†๏ธ Upload</h2>

        <button onclick="uploadTest()">
            Start Upload Test
        </button>

        <div id="upload" class="result">โ€”</div>

    </div>

</div>

<script>

async function downloadTest() {

    const output = document.getElementById("download");

    output.innerText = "Testing...";

    const start = performance.now();

    const response = await fetch("/download?size=100");

    const data = await response.arrayBuffer();

    const end = performance.now();

    const seconds = (end - start) / 1000;

    const megabits =
        (data.byteLength * 8) / seconds / 1000000;

    output.innerText =
        megabits.toFixed(2) + " Mbps";
}


async function uploadTest() {

    const output = document.getElementById("upload");

    output.innerText = "Testing...";

    const size = 50 * 1024 * 1024;

    const data = new Uint8Array(size);

    const start = performance.now();

    await fetch("/upload", {
        method: "POST",
        body: data
    });

    const end = performance.now();

    const seconds = (end - start) / 1000;

    const megabits =
        (size * 8) / seconds / 1000000;

    output.innerText =
        megabits.toFixed(2) + " Mbps";
}

</script>

</body>
</html>
"""


@app.route("/")
def index():
    return render_template_string(HTML)


@app.route("/download")
def download():

    size_mb = min(
        int(request.args.get("size", 100)),
        500
    )

    total_bytes = size_mb * 1024 * 1024

    chunk = b"0" * (1024 * 1024)

    def generate():

        remaining = total_bytes

        while remaining > 0:

            amount = min(
                len(chunk),
                remaining
            )

            yield chunk[:amount]

            remaining -= amount

    return Response(
        generate(),
        mimetype="application/octet-stream"
    )


@app.route("/upload", methods=["POST"])
def upload():

    received = 0

    while True:

        chunk = request.stream.read(1024 * 1024)

        if not chunk:
            break

        received += len(chunk)

    return {
        "received_bytes": received
    }


if __name__ == "__main__":

    app.run(
        host="0.0.0.0",
        port=8000,
        threaded=True
    )

Save the file.


5๏ธโƒฃ Start the Server

Run:

python app.py

You should see something similar to:

Running on http://127.0.0.1:8000
Running on http://192.168.1.25:8000

The exact IP will be different on your network.


6๏ธโƒฃ Test It on the Same Phone

Open your browser:

http://127.0.0.1:8000

You'll see:

๐Ÿ“ถ Local Speed Test

โฌ‡๏ธ Download
[ Start Download Test ]

โฌ†๏ธ Upload
[ Start Upload Test ]

7๏ธโƒฃ Find Your Local IP

On Android/Termux:

ip addr

Find the Wi-Fi IPv4 address.

For example:

192.168.1.25

8๏ธโƒฃ Connect Your Second Device

Connect your laptop/second phone to the same Wi-Fi network.

Open:

http://192.168.1.25:8000

Now the browser on the second device is communicating directly with your local server.


9๏ธโƒฃ Run the Download Test

Tap:

Start Download Test

The browser downloads a generated test payload from the server.

The JavaScript measures:

Downloaded bytes
        รท
Elapsed time
        โ†“
Mbps

Example:

โฌ‡๏ธ Download

287.42 Mbps

This is a local-network measurement, not your Internet speed.


๐Ÿ”Ÿ Run the Upload Test

Tap:

Start Upload Test

The browser generates a 50 MB payload and sends it to the server.

Example:

โฌ†๏ธ Upload

214.73 Mbps

Again, this measures the connection between the two devices.


1๏ธโƒฃ1๏ธโƒฃ Why Local Testing Is Useful

Suppose your Internet speed is:

Internet
500 Mbps

But transferring a file between your phone and laptop is only:

35 Mbps

The problem could be somewhere in your local Wi-Fi connection, rather than your Internet connection.

A local test helps separate:

Internet speed
        โ†“
ISP / Internet

from:

Local speed
        โ†“
Phone โ†’ Wi-Fi โ†’ Router โ†’ Laptop

1๏ธโƒฃ2๏ธโƒฃ Test Different Locations

Try the same test while moving your phone:

๐Ÿ“ Next to router
๐Ÿ“ Same room
๐Ÿ“ Another room
๐Ÿ“ Behind walls
๐Ÿ“ Farther from router

Record the results.

You might see something like:

Near Router
Download: 620 Mbps

Another Room
Download: 310 Mbps

Far Room
Download: 95 Mbps

This gives you a simple picture of Wi-Fi performance around your home.


1๏ธโƒฃ3๏ธโƒฃ Test Different Devices

You can use:

Android โ†’ Laptop
Laptop โ†’ Android
Android โ†’ Android
Laptop โ†’ Laptop

The same server can be used for multiple tests.


1๏ธโƒฃ4๏ธโƒฃ Add Ping Testing

You can also add a simple endpoint:

@app.route("/ping")
def ping():
    return "pong"

Then JavaScript can repeatedly request:

/ping

and calculate the response time.

Example:

Ping: 8 ms

Lower latency generally means a more responsive connection.


1๏ธโƒฃ5๏ธโƒฃ Add a Live Test Screen

You can improve the interface to show:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚    ๐Ÿ“ถ Local Speed Test  โ”‚
โ”‚                         โ”‚
โ”‚       287 Mbps          โ”‚
โ”‚      Download           โ”‚
โ”‚                         โ”‚
โ”‚       214 Mbps          โ”‚
โ”‚       Upload            โ”‚
โ”‚                         โ”‚
โ”‚        8 ms             โ”‚
โ”‚         Ping            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

You can also add an animated speedometer later.


1๏ธโƒฃ6๏ธโƒฃ Important Accuracy Point

This browser-based project is great for learning and quick local comparisons, but don't treat a single result as laboratory-grade network benchmarking.

Your result can be affected by:

  • Wi-Fi signal
  • Router performance
  • Phone CPU
  • Browser
  • Server CPU
  • Background downloads
  • Wi-Fi congestion
  • Network configuration

For more rigorous bandwidth testing, iPerf3 is specifically designed for active network bandwidth measurements and supports TCP/UDP testing and reporting.


1๏ธโƒฃ7๏ธโƒฃ Try iPerf3 for Advanced Testing

If you want a more professional command-line test, install iPerf3 on two compatible devices.

On the server:

iperf3 -s

On the client:

iperf3 -c 192.168.1.25

The official iPerf documentation uses this client/server model and supports options such as test duration, parallel streams, TCP/UDP, and JSON output.

Official website:

https://iperf.fr/


1๏ธโƒฃ8๏ธโƒฃ Add Multiple Test Sizes

Instead of always testing 100 MB, create:

Quick Test
25 MB

Normal Test
100 MB

Large Test
500 MB

This lets you compare short and longer transfers.


1๏ธโƒฃ9๏ธโƒฃ Add Test History

Store results like:

23 Sep
Download: 612 Mbps
Upload: 438 Mbps
Ping: 7 ms

24 Sep
Download: 574 Mbps
Upload: 421 Mbps
Ping: 9 ms

Then display them as a simple graph.


2๏ธโƒฃ0๏ธโƒฃ Stop the Server

When you're finished:

CTRL + C

The local speed-test website will stop.


๐Ÿš€ Final Result

Your setup becomes:

              ๐Ÿ“ถ Wi-Fi
                 โ”‚
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚                   โ”‚
   ๐Ÿ“ฑ Android           ๐Ÿ’ป Laptop
   Python/Flask           Browser
       โ”‚                   โ”‚
       โ””โ”€โ”€โ”€โ”€ Speed Test โ”€โ”€โ”€โ”˜

And the browser can show:

๐Ÿ“ถ LOCAL NETWORK SPEED

โฌ‡๏ธ Download
287.42 Mbps

โฌ†๏ธ Upload
214.73 Mbps

๐Ÿ“ก Ping
8 ms

Python:

https://www.python.org/

Flask:

https://flask.palletsprojects.com/

Python HTTP Server Documentation:

https://docs.python.org/3/library/http.server.html

iPerf3:

https://iperf.fr/

iPerf3 Documentation:

https://iperf.fr/iperf-doc.php

Termux:

https://github.com/termux/termux-app

Note: Keep this server on your trusted local network. Python's basic http.server is explicitly not intended for production use; this project is for local testing and learning.ย 

Report Page