First scan walkthrough
For operators · running scans
TutorialThis tutorial takes you end-to-end on your first scan — installing
Adler, running it, reading the output, hitting Uncertain, fixing
Uncertain, watching the verdict improve, exporting a case file, and
saving the workflow for next week. It’s longer than the
Quickstart because the goal here isn’t a 60-second demo;
it’s making sure you actually understand what Adler is doing before
you scale it up.
You’ll spend about 15 minutes. By the end, you’ll have:
- A working install
- One real scan you’ve inspected
- Signal evidence and confidence reasons you can explain
- A working remedy for at least one
Uncertainrow - A case-file export path for handoff or downstream tooling
- A repeatable workflow (
--watch) for tracking the same name week to week
Step 1 — Install
Section titled “Step 1 — Install”Pick whichever path matches your machine; both arrive at the same
adler binary on PATH:
# Pre-built binaries (fastest)cargo binstall adler-cli
# Or compile from source (~1–2 min)cargo install adler-cliIf you want the TLS-fingerprint impersonation
transport (Chrome 134 handshake emulation; needed for some sites tagged
protection: tls-fingerprint), add --features impersonate to the
cargo install flavour. The binstall flavour ships impersonate
pre-built on 4/5 supported targets.
Confirm:
adler --version# adler 0.15.0The Install page covers every flavour in more depth if you hit a build error.
Step 2 — Your first scan
Section titled “Step 2 — Your first scan”Pick a username you know exists on at least one site — a real human’s
GitHub handle works. We’ll use torvalds:
adler --explain torvaldsWhat you see:
- Text streams in as outcomes resolve — that’s the default
interactive renderer. Found rows in green, Uncertain rows in amber,
NotFound rows hidden by default (pass
--allto include them). - Categorised —
dev,social,forum, etc., based on each site’s tags. - Per-row metadata — elapsed time, verdict reason for Uncertain rows, confidence score when available, and the transport chip when it’s not plain HTTP.
- Explainability lines —
--explainprints the signal evidence, confidence reasons, and any structured profile evidence attached to the outcome.
Expect mostly Found for torvalds (he’s on a lot of dev platforms)
and a sprinkle of Uncertain (CDN edges, login walls).
Step 3 — Understanding the output
Section titled “Step 3 — Understanding the output”The verdict model is the most important thing in Adler. Three states:
| State | What it means | Trust it? |
|---|---|---|
Found | The site returned a working response that confirms the account exists. | Yes. |
NotFound | The site returned a working response that confirms the account does not exist. | Yes. |
Uncertain(reason) | The site responded, but the response can’t tell Found from NotFound. The reason says why. | No — and you should figure out why. |
Adler’s whole identity is in that third row. See
Honest verdicts for the philosophy; the practical
implication is: an Uncertain is not a failure of Adler, it’s
information about the site or your network.
Confidence is the second thing to read. It is conservative and
explainable: signal evidence, exact username matches, authenticated
access, browser/impersonate transports, rich profile metadata, and
stable history can raise it; weak status-only results, blocked
transports, session-required paths, CAPTCHA, and rate-limits keep it
low. The reasons are printed by --explain and are serialized in JSON,
Web, MCP, and reports.
For a focused explanation pass, inspect a small subset:
adler --explain --only github,gitlab torvaldsYou’ll see the signal that produced each verdict. On Found, that’s
the matching status / body marker / redirect rule, plus confidence
reasons such as found by detection signal or exact username match.
On Uncertain, it’s the
UncertainReason — typically something
like cloudflare_challenge, rate_limited, geo_unavailable, or
session_required.
When you need profile evidence for correlation, add enrichment:
adler --enrich --explain --only github,gitlab torvaldsStructured profile_evidence is intentionally narrow: display names,
bio snippets, avatar URLs, external links, locations, exact username
evidence from explicit registry signals, and opt-in avatar hashes.
Identity clusters use these structured fields; username-only overlap is
not enough to merge accounts.
Step 4 — Why is anything Uncertain?
Section titled “Step 4 — Why is anything Uncertain?”Almost always the answer is your scan source. Datacenter IPs (the
default for cloud VMs and most home dev boxes routed through corporate
egress) are pre-banned at CDN edges like Cloudflare and Akamai. From
those IPs, sites that work fine in a browser return interstitial
challenges to plain HTTP — and Adler honestly reports
Uncertain(cloudflare_challenge) rather than guessing.
To confirm this is what’s happening, pipe a JSON dump through jq:
adler --format ndjson torvalds | \ jq -r 'select(.kind == "uncertain") | "\(.site)\t\(.reason)"' | \ sort | uniq -c | sort -rnIf the top reasons are cloudflare_challenge / rate_limited —
that’s a network problem, not an Adler bug. Step 5 fixes it.
If the top reason is geo_unavailable — that site has an access
policy that needs a country-specific egress;
see Access engine → Egress pool.
If the top reason is session_required — that site needs a logged-in
session; see Access engine →
Sessions.
Step 5 — Your first remedy
Section titled “Step 5 — Your first remedy”Cheapest first: tell Adler to route through a residential proxy. Any SOCKS5 or HTTP proxy you control works — paid residential pools (BrightData, DECODO, IPRoyal, Smartproxy) typically give you the best ratio of low ban rate per dollar, but a Tor exit also works in a pinch (slow, but unbanned by most non-Cloudflare edges):
adler --proxy socks5://USERNAME:PASSWORD@HOST:PORT torvalds# Or, for a one-off Tor sweep:adler --tor torvaldsRe-run the jq aggregation from Step 4 against the new output. The
cloudflare_challenge and rate_limited rows should shrink dramatically
— sometimes to zero.
If you want to handle the bot-protected subset (Instagram, X) too,
add a browser backend on top:
adler --proxy socks5://... \ --browser-backend local \ torvaldsLocal Chrome (--browser-backend local) is free; Browserbase’s cloud
sessions (--browser-backend browserbase, ~$0.05/min) buy you a
residential-IP-with-anti-fingerprinting backend for the bot-protected
edge cases. Both bounded by --browser-budget (default 50 fetches per
scan) so a misconfigured flag can’t burn a quota.
Step 6 — Compare the before and after
Section titled “Step 6 — Compare the before and after”You can prove the remedy worked with the built-in cache + the Doctor:
# Save the "before" snapshotadler --format ndjson torvalds > before.ndjson
# Switch to remedied config and re-scanadler --proxy socks5://... \ --browser-backend local \ --format ndjson torvalds > after.ndjson
# Diff the verdict countsfor f in before.ndjson after.ndjson; do echo "=== $f ===" jq -r '.kind' "$f" | sort | uniq -cdoneExpected shape: found goes up, uncertain goes down. NotFound stays
roughly flat (unless Adler now sees sites where the proxy IP is itself
banned — possible but rare on quality residential pools).
Step 7 — Export a case file
Section titled “Step 7 — Export a case file”When a result is leaving your terminal, export an investigation report instead of handing over raw scan rows. Reports combine summary counts, found accounts, high-confidence accounts, signal evidence, normalized profile evidence, confidence reasons, identity clusters, timeline events, and limitations.
The easiest route is the Web UI:
adler --web# Open http://127.0.0.1:8080, run a scan, wait for Done, use JSON / Markdown / HTML exports.The scan id is visible in the route (#/scan/<id>). The same persisted
scan can be rendered from the CLI:
adler --report-scan <SCAN_ID> > report.mdadler --report-scan <SCAN_ID> --report-format json > report.jsonadler --report-scan <SCAN_ID> --report-format html > report.htmlUse Markdown for notes and tickets, JSON for downstream tools, and HTML for a self-contained local case file. HTML reports are offline-safe: inline CSS, no JavaScript, and no automatic external avatar/image loads. See Investigation reports for the full report model.
Step 8 — Make it a workflow
Section titled “Step 8 — Make it a workflow”Two patterns to graduate from “one-off scan” to “I monitor this name”:
Pattern A — watch mode. Re-scan periodically and surface diffs:
adler --watch torvalds # diff vs last cached runadler --watch --interval 86400 torvalds # re-scan every 24hThe watch mode keeps the scan cache at ~/.cache/adler/ and prints
only the rows that changed — new accounts, removed accounts, flipped
verdicts. Pipe it into your alert channel of choice.
Pattern B — Web UI for visual review. If you want a real interface with history, side-by-side diff, evidence drawers, confidence chips, identity clusters, report exports, and the access engine view, launch the bundled SPA:
adler --web# http://127.0.0.1:8080See the Web UI page for the full feature tour.
What you’ve learned
Section titled “What you’ve learned”- Adler’s three-verdict model and why
Uncertainis information, not failure. - How to inspect signal evidence, confidence reasons, and profile
evidence with
--explain,--enrich, and--format ndjson. - That datacenter IPs cause most
Uncertains and how to remedy them. - How to layer a residential proxy + browser backend.
- How to export a case-level investigation report.
- Two workflow patterns for tracking a name over time.
Where to read next
Section titled “Where to read next”- Access engine — the full toolkit (browser backend, escalation, egress pool, sessions, impersonation) once you hit edge cases this tutorial didn’t cover.
- Web UI — the SPA’s feature tour, including per-scan egress subset selection, identity clusters, and report exports.
- Investigation reports — Markdown, JSON, HTML, Web API, and MCP case-file output.
- Honest verdicts — the philosophy doc behind the three-verdict model.
- FAQ — common edge cases and gotchas.
- Glossary — terminology lookup.