Skip to content

Hexadecinull/NetSpeed

Repository files navigation

NetSpeed

Open-source, ad-free internet speed test. Self-hostable, privacy-respecting, and lightweight.

Platforms: Web · Android · (iOS / Desktop — roadmap) License: GPL-3.0


Features

  • Download, upload, ping, and jitter measurement
  • Multi-stream parallel testing for accuracy
  • ISP and IP detection (via self-hosted server)
  • Test history (localStorage / Room DB on Android)
  • Light and dark themes
  • Material You dynamic colors on Android 12+
  • Share results as plain text
  • Zero ads, zero tracking, zero telemetry

Architecture

netspeed/
├── web/                  Vanilla JS web app (GitHub Pages)
│   ├── index.html
│   ├── css/main.css
│   └── js/
│       ├── config.js     Runtime configuration
│       ├── speedtest.js  Measurement engine
│       ├── history.js    localStorage history
│       └── app.js        UI controller
├── server/               Node.js test server (self-hostable)
│   ├── server.js
│   ├── package.json
│   └── Dockerfile
└── android/              Native Android app (Java, Material You)
    └── app/src/main/java/io/github/hexadecinull/netspeed/
        ├── engine/       SpeedTestEngine, SpeedTestResult
        ├── ui/           Activities, Fragments, custom GaugeView
        └── data/         Room database, DAO

Measurement Methodology

Ping / Jitter Sends 20 HEAD requests to /ping sequentially (150 ms apart), measures RTT with performance.now() (web) or System.nanoTime() (Android). Trims 1 outlier from each end, reports median. Jitter is mean absolute deviation of consecutive samples.

Download Opens N parallel HTTP streams fetching chunks from /download?size=25 (25 MB each). Reads response body in a streaming fashion, accumulating total bytes. Speed is computed as (totalBytes × 8) / elapsed_seconds / 1,000,000 Mbps. Runs for the configured duration (default 12 s).

Upload Generates a seeded random byte buffer (16 MB per stream) and POSTs it to /upload repeatedly until the duration expires. Tracks bytes sent via XMLHttpRequest.upload.onprogress (web) or OutputStream.write byte counting (Android).


Self-Hosting the Server

Docker (recommended)

docker build -t netspeed-server ./server
docker run -d \
  -p 8080:8080 \
  -e CORS_ORIGIN=https://yourdomain.com \
  --name netspeed \
  netspeed-server

Node.js

cd server
node server.js

Environment variables:

Variable Default Description
PORT 8080 Listen port
CORS_ORIGIN * Allowed CORS origin
MAX_UPLOAD_MB 500 Max upload body size
GARBAGE_SIZE_MB 100 Max single download response size

Reverse Proxy (nginx)

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_buffering off;
    proxy_request_buffering off;
    client_max_body_size 0;
}

Web App (GitHub Pages)

The web app is a static site in /web/. It deploys automatically via GitHub Actions on every push to main.

Configure your server URL directly in the Settings panel (⚙) — it persists in localStorage.


Android

Requires Android 8.0+ (API 26). Material You dynamic colors activate automatically on Android 12+ (API 31).

Build with Android Studio or:

cd android
./gradlew assembleRelease

Permissions required: INTERNET


Roadmap

  • iOS (Swift, SwiftUI)
  • Desktop (Electron wrapping web app for quick release; Qt/C++ native later)
  • Packet loss estimation
  • Multiple server selection UI
  • IPv4/IPv6 toggle
  • Result sharing image card

Contributing

PRs welcome. Please follow the existing code style: no inline comments, complete files only, no placeholders.


License

GNU General Public License v3.0 — see LICENSE.

About

An open source internet speed tester

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors