A full-stack internet speed test web app built with Node.js + Express (backend) and a rich Tailwind + D3.js + Three.js frontend.
The app measures:
- Latency (ping)
- Jitter
- Packet loss
- Download speed
- Upload speed
It also detects network context (IP, ISP, ASN/network, nearest test server), visualizes real-time test activity, and stores recent results in browser local storage.
npm install
npm startOpen http://localhost:3000 in your browser and click Start Test.
- Overview
- Features
- Tech Stack
- Project Structure
- How It Works
- API Endpoints
- Getting Started
- Configuration
- Usage
- Data & Privacy Notes
- Troubleshooting
- Performance Notes
- Limitations
- Future Improvements
- License
SpeedTest Pro is a browser-based speed testing application that runs a multi-phase test workflow:
- Latency phase: Repeated requests to
/api/pingestimate ping and jitter; failures count toward packet loss. - Download phase: Streaming binary payloads from
/api/downloadover a fixed duration to estimate throughput. - Upload phase: Uploading a generated binary blob to
/api/uploadto estimate outbound speed.
The UI presents test metrics in a modern dashboard, includes a D3 gauge and trend charts, and displays network metadata from IP geolocation/ASN lookups.
- Multi-phase speed test orchestration (ping → download → upload).
- Live gauge animation with dynamic color themes based on current phase and speed band.
- Real-time speed-difference chart (delta between consecutive samples).
- Packet loss estimation from failed ping samples.
- Unit toggle support:
- Bit-based:
bps,Kbps,Mbps,Gbps - Byte-based:
B/s,KB/s,MB/s,GB/s
- Bit-based:
- Public/private IP handling and normalization.
- ISP + ASN/network resolution using:
ipwho.isapi.bgpview.io
- Nearest speed-test server selection by geodesic distance (Haversine formula).
- Animated Three.js particle background.
- D3 circular gauge with needle transitions.
- D3 history chart for recent tests.
- Modal result view with share/download actions.
- Local history persistence (up to 20 entries, 5 displayed in sidebar).
- Node.js
- Express
^4.18.2 - Built-in
httpsmodule for third-party lookups
- HTML/CSS/Vanilla JavaScript
- Tailwind CSS via CDN
- D3.js v7 via CDN
- Three.js r128 via CDN
SpeedTest/
├─ package.json
├─ package-lock.json
├─ server.js
└─ public/
├─ index.html
├─ app.js
└─ styles.css
- Serves static assets from
public/. - Exposes API endpoints for ping/download/upload/network info.
- Determines client IP using
x-forwarded-for(first value) or socket IP. - Calls IP intelligence providers with timeout-protected HTTPS requests.
- Picks nearest logical test server from a static region list.
- Falls back to
public/index.htmlfor unmatched routes.
- Initializes on
DOMContentLoaded:- connection type detection,
- network metadata fetch,
- Three.js scene,
- D3 gauge/realtime/history charts,
- history loading.
- Runs tests sequentially with UI phase updates and event logging.
- Updates primary metric cards and gauge continuously.
- Saves test summaries into localStorage (
speedTestHistory).
- Tailwind utility classes define layout/theme.
- Custom CSS adds scrollbar, glow effects, responsive gauge sizing, and animation polish.
Returns current server timestamp.
Response
{ "t": 1739790000000 }Streams binary payload for throughput testing.
Behavior
- Min size:
1024bytes - Default size:
5MB - Max size:
100MB - Content type:
application/octet-stream
Accepts raw upload body and returns total bytes + elapsed server-side duration.
Response
{ "bytes": 15728640, "durationMs": 1234.56 }Returns resolved network metadata and selected server.
Response shape
{
"ip": "203.0.113.10",
"isp": "Example ISP",
"network": "AS12345 Example Network",
"server": {
"name": "West Africa - Lagos",
"host": "lagos.speedtest.local",
"location": "Lagos, NG",
"distanceKm": 12.34
}
}- Node.js 18+ recommended
- npm 9+ recommended
- Internet access (for external JS CDNs and IP intelligence APIs)
npm installnpm startServer starts on:
http://localhost:3000(default)- or
http://localhost:<PORT>ifPORTis set
npm run dev(Currently identical to npm start.)
PORT: HTTP port for Express server.
Example (PowerShell):
$env:PORT=8080
npm start- Open the app in your browser.
- Wait for connection/network metadata to populate.
- Click Start Test.
- Observe live metrics during:
- Latency test
- Download test
- Upload test
- Review result cards, charts, and history.
- Use Results tab/modal to share or download summary.
- Test history is stored in browser local storage (
speedTestHistory). - The backend queries external services (
ipwho.is,bgpview) using detected public IP when available. - No database is used in this project.
- Ensure dependencies are installed:
npm install. - Verify Node.js version is modern (18+ recommended).
- Check if port is already in use; change
PORT.
- External APIs may be unreachable, rate-limited, or blocked.
- Corporate VPN/proxy/private IP environments may limit geolocation/ASN accuracy.
- Browser load, background downloads, Wi-Fi variability, and ISP traffic shaping affect measurements.
- Try running tests multiple times and compare trends rather than one-off peaks.
- Tailwind/D3/Three are loaded via CDN in
index.html; offline environments will need local bundling.
- Download throughput uses repeated streamed fetches and periodic UI updates (~200ms).
- Upload test uses
XMLHttpRequestprogress events for smoother sampling. - Realtime difference chart keeps a rolling window of 60 points.
- This is not equivalent to enterprise-grade speed testing networks with globally distributed edge nodes.
- Server selection is logical/geographic from a static list, not actual distributed test infrastructure.
- External geolocation/ASN services are best-effort and may return incomplete data.
- No authentication, rate limiting, or abuse protection is implemented by default.
- Replace CDN scripts with bundled frontend assets.
- Add automated tests (API + UI).
- Add server-side observability and health checks.
- Add configurable server regions via environment/config file.
- Add Docker support and CI pipeline.
No license file is currently defined in this repository.
If this project is intended for public use, add a LICENSE file (e.g., MIT) and update this section.