Measure your WiFi for real. No app to install. Nothing touching your router. Your ISP never enters the picture.
One command on a laptop, one QR code, and your phone becomes a Geiger counter for WiFi.
[ Laptop next to the router ] ←—— the air (this is what we measure) ——→ [ Phone, walking ]
npx faro Safari / Chrome
the lighthouse the ship
npx faro- Run it on a computer next to the router — plugged in by Ethernet if you can.
- Scan the QR code (it prints in your terminal, and shows on the page).
- Stand by the router for 10 seconds. That calibrates 100% for your network.
- Walk your home. Watch the needle.
There is nothing to name, nothing to save, nothing to export. You walk, and it tells you.
One gauge. Six levels. An arrow for which way it's heading as you move.
VERY BAD → BAD → ENOUGH → GOOD → VERY GOOD → EXCELLENT
▲ getting warmer ▼ getting colder = holding steady
The entire background takes on the colour of the level, so you can read it from the corner of your eye while walking with the phone at your side. There's an optional Geiger-counter beep that ticks faster as the signal dies.
This is the question people actually have. When the meter drops into the red, it says:
Walk back toward the router until this says GOOD. That last good spot is where a mesh node belongs.
That's the physically correct answer, and it's the one most people get wrong. A satellite node placed inside the dead zone can't hear the router either — it has to sit at the last point with a solid link and project forward from there.
A speed test measures the internet, not your WiFi. It saturates at your ISP. If your plan gives 300 Mbps and the kitchen delivers 280, then the kitchen and the living room show you the same number — and you have learned nothing about your house.
Survey apps measure RSSI, which is signal strength, not throughput. You can sit at a healthy -60 dBm and still crawl, because of interference or a congested channel. And on iOS they barely exist at all: Apple doesn't expose that API to third parties.
The only honest measurement of WiFi is real throughput between two points on your own LAN. That is the entire idea behind FARO.
| Download | 4 parallel fetch calls pulling 8 MB blobs, read chunk by chunk. A 2-second sliding window makes the number drop live the moment you cross a wall. |
| Upload | 2 parallel POSTs. Upload dies first — your phone transmits with far less power than the access point does — which makes it the sharpest dead-zone detector you have. |
| Latency / jitter | WebSocket echo every 250 ms. |
| Score | 0.5·download + 0.3·upload + 0.2·(1/latency), measured against a baseline frozen during calibration. |
The reference is captured once, during the 10-second calibration next to the router — a high percentile of those samples, deliberately not the peak — and then it never changes.
This is the difference between a meter and a random number generator.
An earlier version kept a running maximum. One lucky 2-second burst would raise the 100% mark permanently, and every reading afterwards got divided by a speed the network can't actually sustain. Walk around long enough, hit one freak peak, and from then on everything read red — including the spot you started from, standing right next to the router.
A meter that gives a different answer for the same place is broken. This one doesn't: walk away, come back, get the same reading. Hit RECALIBRATE (next to the router) any time you want a fresh reference.
- AP / client isolation — some routers block traffic between WiFi clients. Turn it off. (The fact that it was on is itself worth knowing.)
- Firewall — Windows will typically block the port the first time. Allow it on private networks.
- Guest network, or split 2.4/5 GHz bands — the phone has to be on the same network as the laptop.
- iOS Low Power Mode — throttles network activity. Turn it off while you measure.
RSSI, access point names, channel numbers — impossible from a browser, and we don't pretend otherwise. Floor-plan heatmaps. HTTPS, accounts, a stateful backend. And never measuring against the internet: that's the whole point.
faro/
├── server.js static + /blob + /sink + WebSocket ping + LAN IP detect + QR
└── public/
├── index.html
├── app.js measurement, frozen baseline, score, gauge
└── style.css
Two dependencies (ws, qrcode-terminal). No build step, no bundler, no framework. The
whole thing is meant to be readable in ten minutes.
git clone https://github.com/andycufari/faro.git
cd faro && npm install && npm start- WebRTC — real packet loss and jitter via
getStats, plus a two-phone mode where the laptop is only a signalling page and the lighthouse is a second phone by the router. - Hosted —
faro.cm64.studio, so there's nothing to clone at all. - Mesh assistant — "put the lighthouse where the satellite would go, walk, and I'll tell you whether that spot actually covers the house."
MIT · built by Andy Cufari at CM64 Labs