Install howismywifi as a Python CLI tool on macOS, Windows, or Linux.
Installs a venv, the wheel + video deps + Chromium, and runs a readiness check. See the Remote / Headless Linux Deployment guide for the full hands-off workflow.
$ curl -fsSL https://howismywifi.com/download/install.sh | bash
Have Python 3.12+? Install the published wheel straight from the web:
$ pip install "https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl"
$ wifi-capture --preflight # check the box is ready
$ wifi-capture --quick
For video testing (our hosted stream, YouTube and Shorts ABR), install the [field] extra and the Chromium browser:
$ pip install "wifi-monitor[field] @ https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl"
$ python -m playwright install chromium
--upload works off-VPN the moment it's installed. No VPN, GHE
login, or Git required.
$ curl -fsSL https://howismywifi.com/download/install.sh | bash
Updating by hand instead? Upgrade to the current version (keep the [field]
extra so a new video dependency is pulled too) — and re-run the browser install with it:
$ pip install --upgrade "wifi-monitor[field] @ https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl"
$ python -m playwright install --only-shell chromium
The second line matters: the upgrade re-resolves
playwright within its <2 cap, and a newer Playwright expects
a newer Chromium revision than the one on disk — skip it and the video probes
quietly stop producing, with nothing failing at install time.
When you run wifi-capture interactively on a box that's behind, it prints a
one-line “newer build available” notice at startup (checked at most once a
day; silent for headless / --json runs). Silence it with
export WM_NO_UPDATE_CHECK=1.
$ curl -fsSLO https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl.sha256
$ pip install "wifi-monitor[field] @ https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl#sha256=$(cut -d' ' -f1 wifi_monitor-0.1.6-py3-none-any.whl.sha256)"
download/archive/<git-sha>/… key that’s never overwritten, so you can move
a box back to a known-good build (or hold one that must not move). The one-command path
records the pin, so the startup notice tells a rolled-back box it’s
pinned instead of nagging it toward latest:
$ WM_WHEEL_URL=<archive-url> curl -fsSL https://howismywifi.com/download/install.sh | bash
A manual pip install <archive-url> works too, but won’t record the pin (the
box will still get the plain “update available” notice). Full rollback/pin runbook:
remote-headless deployment §7.
macOS includes Python 3 via Xcode Command Line Tools:
$ xcode-select --install # if not already installed
$ python3 --version
Or install via Homebrew: brew install python@3.12
Included with Xcode Command Line Tools. Verify: git --version
Check if you already have Python:
> python --version
If not installed, download from python.org. During install, check "Add Python to PATH".
python3 instead of python.
Check: git --version. If not installed, download from git-scm.com.
# Ubuntu / Debian
$ sudo apt install python3 python3-pip
# Fedora
$ sudo dnf install python3 python3-pip
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ uv venv --python 3.12 ~/wm-venv && source ~/wm-venv/bin/activate
The wheel install needs neither Git nor VPN.
Install the published wheel — no clone, no Git, no VPN:
$ python3 -m venv ~/wm-venv && source ~/wm-venv/bin/activate
$ pip install "wifi-monitor[field] @ https://howismywifi.com/download/wifi_monitor-0.1.6-py3-none-any.whl"
$ python -m playwright install chromium # only if you'll run video probes
The [field] extra adds video (Playwright) and local-analysis
support. For the core CLI only, drop [field] and install the bare URL.
The hosted-video, YouTube and Shorts ABR probes need Playwright and a Chromium browser binary.
The [field] extra installs Playwright; the browser is a separate,
one-time download:
$ python -m playwright install chromium
$ sudo python -m playwright install-deps chromium # Linux only, if launch fails
Verify everything works with a 30-second capture:
$ wifi-capture --quick
# 30-minute timed capture with analysis chart
$ wifi-capture --duration 30m --analyze
# Continuous capture (Ctrl+C to stop)
$ wifi-capture --analyze
# Select specific probes
$ wifi-capture --probes ping,http,dns --duration 10m
# Tag metadata upfront (skip prompts)
$ wifi-capture --location "SEA-JFK" --network "Inflight WiFi" --duration 30m
For a hands-off long run on a remote box — detached, uploading, no terminal. Full walkthrough: Remote / Headless Linux Deployment.
$ wifi-capture --preflight # confirm Python, Chromium, RAM, disk, upload egress
$ nohup wifi-capture --schedule more-video --duration 24h --allow-metered --upload \
--location "Lab-Office" --network "Office-WiFi" > wm-run.log 2>&1 &
$ pgrep -cf bin/wifi-capture # confirm exactly one is running → 1
--upload is required — without it the capture stays local and never reaches the results site.--location/--network so the run never waits on a prompt (headless runs skip prompts automatically, but the tags are still worth setting).more-video is the unmetered choice; budget-video is for metered cellular and requires --data-budget.--metered yes (choices yes/no/unknown, default unknown = not metered). It caps each speed test's download at 100 MB (instead of 200 MB) and its upload at 100 MB and marks the rows metered=1. A --data-budget run applies the same caps on its own. Not the same as --allow-metered, which only acknowledges a heavy schedule.$ wifi-manage reanalyze <capture-id>
(The CLI prints this exact command with the id when a capture crosses the limit.)
Generate an interactive HTML results page for a capture:
$ wifi-results captures/your-capture.csv
For a multi-capture comparison, use the live report at howismywifi.com/compare — it groups every uploaded capture by provider, venue, and satellite.
| Command | Purpose |
|---|---|
wifi-capture | Run a network measurement capture |
wifi-results | Generate interactive HTML results page from a capture CSV |
wifi-manage | Manage captures (list, archive, delete). wifi-manage pull syncs shared captures down from R2 — admin R2 credentials required. |
ping and traceroute (no raw socket permissions needed)scripts/wifi_capture.sh handles venv + capture + analysisicmplib (pure Python)netsh wlan show interfaceswifi-capture is not found, try python -m wifi_monitor.cliicmplib (may need sudo or CAP_NET_RAW)