Command-Line Install

Install howismywifi as a Python CLI tool on macOS, Windows, or Linux.

Fastest — one-command bootstrap (remote / off-VPN box)

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
Manual — remote / off-VPN box (no clone, no Git)

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
The wheel is self-contained — it bundles the upload credentials, so --upload works off-VPN the moment it's installed. No VPN, GHE login, or Git required.
Updating an existing install? Every release has a new version number. On a box installed via the one-command bootstrap, re-run the installer — it's the safe update path:
$ 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.
Verify the download (optional). A checksum is published next to the wheel — pin it at install so a corrupted download fails loudly:
$ 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)"
Roll back or pin a build. Every publish also lands under an immutable 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.

Prerequisites

1
Python 3.12+

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

2
Git

Included with Xcode Command Line Tools. Verify: git --version

1
Python 3.12+

Check if you already have Python:

> python --version

If not installed, download from python.org. During install, check "Add Python to PATH".

Windows Store Python also works. If you have multiple versions, use python3 instead of python.
2
Git

Check: git --version. If not installed, download from git-scm.com.

1
Python 3.12+ (Git optional)
# Ubuntu / Debian
$ sudo apt install python3 python3-pip

# Fedora
$ sudo dnf install python3 python3-pip
System Python older than 3.12? Install uv and let it provide 3.12 without touching the system:
$ 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

3a
Install the CLI

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.

3b
Video testing (Playwright + Chromium)

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
Without this, video rounds silently do nothing. The probes skip when Playwright/Chromium is absent, so a video-first schedule would produce zero video with no error. Headless Chromium also needs ~0.5–1 GB free RAM per instance — on a low-memory box, navigations time out.

Run a Capture

4
Quick test

Verify everything works with a 30-second capture:

$ wifi-capture --quick
5
Full capture
# 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
5b
Unattended / headless run (detached, uploading)

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.
  • Pass --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.
  • On a metered link, pass --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.
Very long captures & the analysis limit. The server analyzes uploads up to a size limit; most day-long runs are under it, but a very long (multi-day) capture can exceed it and the results page will show blank stats until you generate them. Recover it from the same box — no admin access needed:
$ wifi-manage reanalyze <capture-id>
(The CLI prints this exact command with the id when a capture crosses the limit.)

Analyze and Report

6
Generate results pages and reports

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.

Available Commands

CommandPurpose
wifi-captureRun a network measurement capture
wifi-resultsGenerate interactive HTML results page from a capture CSV
wifi-manageManage captures (list, archive, delete). wifi-manage pull syncs shared captures down from R2 — admin R2 credentials required.

Platform Notes

Prefer the native app? The Windows app provides the same functionality with a graphical interface, live charts, and automatic setup.