Newwhatleaks 0.1.0: in a lab with exact ground truth it silently missed 3.4% of attempts on macOS, mitmproxy 38%whatleaks 0.1.0 missed 3.4%, mitmproxy 38%
v0.1.0Open-source CLI · MIT · macOS and Linux

See what your tools send home.

whatleaks runs any command through a local, single-run proxy and shows where its traffic went, which fields it carried, whether any of it is about you, and what it still sends after you opt out.

$npx whatleaks run -- <command>
Get started →

Node ≥ 22.12No accountNothing added to your trust store

real output · Next.js 16.4.2
$ npx whatleaks compare --no-known-opt-outs --off-env DO_NOT_TRACK=1 -- ./node_modules/.bin/next build

whatleaks diff · before "default" (3.7 s, 9 requests) → after "opted-out" (3.1 s, 9 requests)
command: ./node_modules/.bin/next build
opted out with: DO_NOT_TRACK

The telemetry endpoint was still contacted after opting out.
Telemetry requests: 8 → 8 · all requests: 9 → 9

STILL SENDING AFTER OPT-OUT
  ● POST telemetry.nextjs.org/api/v1/record  analytics · Next.js telemetry  8 → 8 requests
      still sent: context.anonymousId, context.projectId, context.sessionId, events[].eventName, meta.agentName, meta.ciName, meta.cpuCount, meta.cpuModel, meta.cpuSpeed, meta.isCI …+81

OTHER TRAFFIC
  (not identified as telemetry; check it yourself)
  = POST registry.npmjs.org/-/npm/v1/security/advisories/bulk  other  1 → 1

STILL SENT ABOUT YOU
  ○ Repeated identifiers — 8 requests, in context.anonymousId, context.projectId, context.sessionId

PERSISTENT IDENTIFIERS
  same value in both runs: stored by the app or built into it, so it can link runs together
  ○ ‹id-1› at context.anonymousId → POST telemetry.nextjs.org/api/v1/record
  ○ ‹id-2› at context.projectId → POST telemetry.nextjs.org/api/v1/record
Real output from next build (Next.js 16.4.2, Node 22.23) on 2026-10-21, printed from the saved captures. Next.js documents NEXT_TELEMETRY_DISABLED, not DO_NOT_TRACK.Full transcripts →
Benchmarked with real clients Node 20 · 22 · 26BuncurlPython: urllib, requests, httpx, aiohttpRubyGoJavaWebSocketsHTTP/2raw TCP and UDP
01 · What it finds

Find out what it says about you.

Every payload is decoded and every field inventoried. whatleaks searches it for this machine's identifiers, raw and hashed, and flags the ids an app keeps between runs.

It looks for you in every request

  • Your username, hostname, home path, MAC address, machine id and git email, raw or as md5, sha1 and sha256 hex or base64.
  • Ids that repeat across requests, and ids that stay the same between runs: stored by the app, so they can link your runs together.
  • Where each field appeared and how often, with a redacted sample you can post.

In this run Next.js sent none of this machine's identifiers. It sent its own persistent ids, the hardware it ran on, and the AI agent that ran the build.

POST telemetry.nextjs.org/api/v1/recordsample 1 of 8
{
  "context": {
    "anonymousId": "‹id-1›",   // same in a second run
    "projectId": "‹id-2›",     // same in a second run
    "sessionId": "‹id-3›"
  },
  "meta": {
    "systemPlatform": "darwin",
    "systemRelease": "25.6.0",
    "systemArchitecture": "arm64",
    "cpuCount": 8,
    "cpuModel": "Apple M1",
    "cpuSpeed": 2400,
    "memoryInMb": 8192,
    "isDocker": false,
    "isNowDev": false,
    "isWsl": false,
    "isCI": false,
    "ciName": null,
    "nextVersion": "16.4.2",
    "agentName": "claude-code_2-1-306_agent"
  },
  "events": [ … NEXT_CLI_SESSION_STARTED and 39 config fields ]
}
●Next.js 16.4.2 put the AI agent running the build in all 8 requests. anonymousId and projectId were identical in a second run. Ids are shown as whatleaks's aliases.
02 · Opt-outs, tested

Opted out? Check.

whatleaks compare runs your command twice in fresh processes, first with defaults and then opted out, and shows what is still sent. The restart is built in, so nobody can say you forgot it.

next buildNext.js 16.4.2 · real runs
  1. Defaults8 requests to telemetry.nextjs.org, 22 events8 requests
  2. DO_NOT_TRACK=1Not a switch Next.js documents. It kept sending.8 → 8 · still sending
  3. NEXT_TELEMETRY_DISABLED=1The switch Next.js documents.8 → 0 · stopped
--strict exits 1 when a known telemetry endpoint is still contactedCI-ready

32 documented opt-outs, in one flag

By default the second run sets every opt-out variable whatleaks knows, each with a source. Or test one switch with --no-known-opt-outs --off-env KEY=VALUE.

DO_NOT_TRACK=1NEXT_TELEMETRY_DISABLED=1ASTRO_TELEMETRY_DISABLED=1TURBO_TELEMETRY_DISABLED=1GATSBY_TELEMETRY_DISABLED=1NG_CLI_ANALYTICS=falseSTORYBOOK_DISABLE_TELEMETRY=trueWRANGLER_SEND_METRICS=falseHOMEBREW_NO_ANALYTICS=1DOTNET_CLI_TELEMETRY_OPTOUT=1GH_TELEMETRY=0HF_HUB_DISABLE_TELEMETRY=1+20 more
$ npx whatleaks opt-outs    # the list, with the tools each one covers
03 · Measured

It catches what other tools miss silently.

46 lab scenarios with exact ground truth: each client writes every attempt to a ledger before making it, and each tool's output is scored per attempt.

The full benchmark →
3.4%

of 594 attempts silently missed on macOS, 3.0% of 567 on Linux. Every remaining miss is a Go program whatleaks loads no hook into.

Attempts silently missed

Lower is better. Same scenarios, same ground truth.

mitmproxy 12.2.3 with the same environment whatleaks sets; HTTP Toolkit server 1.27.3 with its own interception.

View as table
ToolmacOSLinux
whatleaks3.4% (20 of 594)3.0% (17 of 567)
mitmproxy38% (225 of 594)40% (225 of 567)
HTTP Toolkit67% (399 of 594)70% (399 of 567)
No false credit

Nothing the app did not send was ever credited to it, in any run.

8 of 8 identifiers, 0 of 4 decoys

Every planted identifier was found in every run, including 3 hidden in a WebSocket message. No decoy was flagged.

5 of 5 real tools

Matched against each tool's own debug output: Next.js on Node 22 and 20, Turborepo, Astro and Wrangler. HTTP Toolkit matched 4, mitmproxy 3.

04 · How it works

Built for the traffic proxies miss.

A proxy sees only what is sent through it. whatleaks also follows the app's processes, hooks the runtimes that ignore proxy settings, and names whatever still goes around.

A CA that lives for one run

Each run makes a fresh certificate authority. Its key stays in memory and its certificate is deleted when the run ends. Your system trust store is never touched.

The whole process tree

Child processes are followed, including detached helpers that keep sending after the app exits. --duration and Ctrl-C stop them all.

Hooks for Node, Python and Ruby

Small preloads route clients that ignore proxy variables, like node:http2 and aiohttp, and report each direct socket as it opens.

Names what goes around

Connections that bypass the proxy are listed by address and process: netstat on macOS, /proc on Linux. Pinned clients are named and counted, never broken into.

Every field, inventoried

JSON, NDJSON, form and binary bodies are decoded. 69 known telemetry hosts carry a source link; keyword guesses are marked ? and never count toward a verdict.

Reports you can post

Your identifiers become labels, secrets become ‹redacted›, ids become aliases. The raw HAR stays on your machine, readable only by you.

05 · Limits

What it can't see.

Measured, not guessed. The numbers are in the benchmark.

Apps that refuse the CA

Pinned clients, and Go programs on macOS (they read only the keychain), fail that request. whatleaks names the host and counts it. It never tries to get around pinning.

Very short sockets from native code

Go, Rust or C connections that skip the proxy are found by polling. One reset within about 10 ms is often missed (Go in the lab: caught 10 to 30% of the time), and UDP sent with sendto() is never seen.

Windows

No process-watching backend yet, so it is untested there. macOS and Linux are benchmarked.

Apps you don't launch

Only processes started through whatleaks are watched. GUI apps, Electron apps, browsers and system daemons were not tested.

Exact matching only

Salted hashes of your identifiers can't be recognised. Redaction is pattern-based, so read a report before you post it.

It's our benchmark

We built the lab. Every script and result file is public, and the threats to validity are written down next to the numbers.

Find out what your tools say about you.

$npx whatleaks run -- <command>
Star on GitHub Read the docs →

Or npm install -g whatleaks. Needs Node ≥ 22.12, on macOS or Linux. Each run saves its capture as a HAR file that only you can read.