A comprehensive, self-updating network health monitor for Windows. Built after two days of fighting hostel Wi-Fi and mobile hotspot congestion. NetPilot measures everything that actually makes a network feel bad, tells you exactly which layer is the problem, learns when your networks are usable, and live-publishes it all to a website that updates itself — demo deployment.
Speedtests measure Mbps. NetPilot measures what hurts: latency, jitter, packet loss, bufferbloat (both directions), DNS behavior, radio congestion — layer by layer.
Jump to: Screenshots · Features · Install · Usage · Web dashboard & Vercel · Scoring · Tests · Architecture
Live dashboard (python netpilot.py):
Full diagnostics (python netpilot.py --full — traceroute, bidirectional
bufferbloat, throughput, path MTU, channel scan, VPN detection):
Web dashboard (python netpilot.py --publish → deploy anywhere, e.g. Vercel):
dark-themed, self-contained HTML with per-network hour-of-day heatmaps,
healthy/dead hour chips, incident timeline and availability — zero external
requests, zero tracking.
| Domain | What | Why it matters |
|---|---|---|
| Local link | latency/loss to your gateway | isolates "laptop ↔ router" problems (distance, interference, adapter sleep) |
| Internet path | latency, jitter, p95, loss to multiple targets | the core "is my network usable" signal |
| Route | hop-by-hop traceroute analysis | pinpoints where on the path the pain starts (e.g. carrier CGNAT) |
| Bufferbloat ↓↑ | latency under download and upload load | "everything lags when someone downloads" — and uploads wreck video calls |
| Throughput ↓↑ | download & upload Mbps | measured during the bloat tests, free of charge |
| DNS | resolver identification, lookup latency, hijack detection | campus/captive portals intercepting DNS cause mystery redirects and stalls |
| Radio environment | channel scan of all nearby APs, co-channel congestion, 5 GHz availability | "your channel has 11 strong neighbours" and "your SSID also has a 5 GHz twin — switch" |
| Path MTU | DF-ping binary search | detects silent large-packet blackholes (common with VPNs/firewalls) |
| VPN awareness | detects WARP / WireGuard / Tailscale / OpenVPN | measurements are interpreted differently when tunneled |
| Events | disconnects, AP roaming, outages, DNS failures | a timeline of incidents, with availability % and week-over-week trends |
Alerts when things go wrong: desktop toast (optional) + Discord webhook
(set alerts.webhook_url in the config) + console. Optional auto-switching to a
backup Wi-Fi when the network is DEAD.
Everything runs with no admin rights and only uses built-in Windows tools
(ping, netsh, route, tracert) — nothing sketchy, nothing phoning home.
Python 3.10+ on Windows.
pip install -r requirements.txt # rich, pandas, matplotlib
pip install plyer pytest # optional: toast notifications / dev testspython netpilot.py # live dashboard (Ctrl+C to stop)
python netpilot.py --once # quick check → exit code 0 GO / 1 WARN / 2 DEAD
python netpilot.py --full # deep diagnostics (~2 min: traceroute, bidirectional
# bloat, throughput, path MTU, channel scan, VPN)
python netpilot.py --report # heatmap + schedules + incidents + trends + HTML
python netpilot.py --report --days 14
python netpilot.py --sync --headless # background collector + live website sync
python netpilot.py --sync-now # one measurement + push to the website, then exit
python netpilot.py --publish --anon # regenerate the deployed site's embedded snapshot
python netpilot.py --auto "MyHotspot" # auto-switch to a saved Wi-Fi after 30s of DEAD
python netpilot.py --deep-interval 15 # live mode: deep diagnostics every 15 minThe routine: run --full once per network to meet it, keep the live monitor
running when you care, check --report after a few days, and --publish when
you want receipts.
The deployed site shows real, live data — no demo, no manual publishing:
collector (your laptop, background) website (Vercel)
┌───────────────────────────────┐ ┌──────────────────────────┐
│ netpilot.py --sync --headless │ every │ index.html fetches │
│ · probes every ~10 s │ 10 min │ data.json from the raw │
│ · logs CSV + incidents │ ────────▶ │ GitHub `data` branch │
│ · pushes web/data.json │ GitHub │ and re-renders itself │
└───────────────────────────────┘ API │ every 60 s 🟢 LIVE │
└──────────────────────────┘
- No rebuilds, no deploy limits — data flows through the repo's
databranch; the static site fetches it client-side. - RIGHT NOW hero card — current verdict/score/latency/loss/jitter, bloat grades, path MTU, VPN state; auto-refreshes every 60 s.
- ICMP-block honesty — if a network blocks ping entirely (some campuses do), the site says so instead of lying "DEAD".
Setup:
python scripts/start-collector.bat # start the background collector now
# auto-start at login: copy scripts/netpilot-collector.vbs into
# %APPDATA%\Microsoft\Windows\Start Menu\Programs\StartupDeploy your own (2 min): python netpilot.py --publish --anon → commit & push
→ vercel.com → Add New → Import repo → Deploy
(vercel.json already points at web/; production is static).
Privacy: the collector pseudonymizes SSIDs (Network A/B/...) before
anything leaves your machine — flip sync.anonymize in the config if you want
real names. Raw logs never leave logs/.
Each domain gets a 0–100 score and a letter grade (A ≥90, B ≥75, C ≥60, D ≥40, else F). The overall score is a weighted roll-up (path 45%, link 25%, DNS 15%, radio 15%, +20% bufferbloat when tested); untested domains are dropped and weights renormalized, so a light cycle still scores fairly.
| Verdict | Meaning | Real-world anchor |
|---|---|---|
| GO (≥75) | do your thing | 48 ms / 0% loss ≈ 93 |
| WARN (40–74) | usable, expect stutters | ~6% loss |
| DEAD (<40) | switch networks or wait | 217 ms avg, wild jitter |
Loss is punished deliberately hard: for real-time anything (games, calls), a few percent of lost packets matters more than raw latency.
Some campus APs ignore pings to the gateway — NetPilot detects this and refuses to blame your local link for it.
python netpilot.py --report produces:
reports/netpilot_report.png— hour-of-day congestion heatmap per networkreports/netpilot_report.html— standalone shareable report: embedded heatmap, per-network healthy/dead hour schedules, recent incidents, week-over-week trends, availability %- console summary, e.g.
Campus-5G (3810 samples) — overall 71/100
healthy hours: 09:00-18:00
dead hours: 19:00-23:00
Phone (922 samples) — overall 88/100
healthy hours: 07:00-09:00, 23:00-07:00
dead hours: 20:00-22:00
Week-over-week trend
Campus-5G: week 1 74 → last week 68 [↓ -6]
Phone: week 1 85 → last week 87 [↑ +2]
Availability (uptime while monitored): 96.42%
python -m pytest tests/ -q # 36 testsThe suite unit-tests the parsers (ping / netsh / route / tracert output against real captured samples), the scoring math (anchored to real-world measurements), traceroute hop parsing, diagnosis logic and report helpers. CI runs the full suite on every push — on a Windows runner, because that's the platform.
netpilot.py CLI + monitoring engine (light cycles, deep cycles, alerts, auto-switch)
prober.py subprocess wrappers + PURE parsers (unit-testable)
health.py rolling stats, per-domain scores, grades, roll-up, diagnosis
dashboard.py the rich layout (live dashboard + full report rendering)
wifi_env.py channel congestion analysis from BSSID scans
dnscheck.py resolver detection, lookup latency, NXDOMAIN hijack test
bloat.py bidirectional bufferbloat + throughput
traceroute.py hop-by-hop path analysis, loss localization
mtu.py path MTU / blackhole detection via DF pings
vpndetect.py WARP/WireGuard/Tailscale/OpenVPN detection
events.py incident detection (outages, roaming, DNS fails) + timeline
logger.py CSV logging (schema v2, auto-migrates v1 files)
report.py heatmap, schedules, incidents, trends, availability, HTML export
notify.py Discord webhook + toast + console alerts
sync.py live-sync: payload builder + GitHub data-branch pusher
web.py --publish: live-fetching web dashboard (single HTML file)
scripts/ collector launcher + screenshot generation
tests/ pytest suite (real captured tool output)
web/ published dashboard (what Vercel serves)
- Windows-only for now (the probe layer parses
ping/netsh/route/tracertoutput). - Deep diagnostics transfer ~10 MB down + ~8 MB up — skip on metered connections
or tune
bloatin the config. - Logs and reports stay in
logs/andreports/— they contain your SSIDs, and both folders are git-ignored by default. - Auto-switch connects only to saved Wi-Fi profiles, only if visible, and backs off for 5 minutes after each attempt.
- System-tray mode (pystray) · Linux/macOS support (probe abstraction)
- Week-over-week network quality charts in the web dashboard
- Auto toggle VPN (WireGuard/WARP) on verdict changes
MIT © 2026 Sainath Reddy
Born from a real situation: campus Wi-Fi that needs a VPN, a WireGuard box on AWS Mumbai, a phone hotspot that dies at 8 pm, and way too many teleports in Valorant.