What this covers
The habits that decide whether an investigation holds up: how you look at a target without telling them, how you record what you found so it survives the page being deleted, and how you avoid deciding the answer before you have it. Most of this sheet is discipline rather than tooling, because most of it has no command — and where a tool genuinely exists, the commands below are the ones that keep you from leaking.
The rule that matters most
Every request you make is a signal to the other side. Viewing a LinkedIn profile notifies its owner. Loading a Telegram channel with your real account puts your username in the member list. Hitting a small target’s website leaves your IP in their logs. A reverse image search on a photo that only three people have seen tells those three people someone is looking.
Decide before you start: is this target likely to notice, and does it matter if they do?
Method
- Write the question down before you collect anything. One sentence, answerable, with a stated standard of proof. “Is this company linked to that one” is not a question; “does any public filing show a shared officer, address or beneficial owner” is.
- Decide your exposure budget first. Which identity touches the target, from what address, and what happens if that address is logged. Changing this mid-investigation is how an account gets burned.
- Capture as you go, never afterwards. Anything interesting is archived the moment you see it. Pages disappear, get edited or go private within hours of someone noticing attention. See Archiving & Evidence Preservation.
- Record the route, not just the result. URL, UTC timestamp, the query that surfaced it, and what you clicked to get there. A screenshot with no source and no date is worth nothing, and the path to a finding is the part you forget first.
- Keep raw separate from conclusions, in different files. One place for what you collected, another for what you think it means. Conflating them is how an assumption becomes a fact three notes later and a published claim three weeks later.
- Log what you looked for and did not find. Negative results stop you re-running the same dead end next week, and they are what an honest report needs in order to describe its own limits.
- Name the thing that would prove you wrong, then go look for it. If you cannot state what evidence would change your conclusion, you are not investigating, you are assembling.
- Stop at the question you wrote down. The collection will always offer you more. More about a bystander, more about a family member, more that is interesting and none of your business.
Key tools
Hunchly
The one tool that removes the discipline problem, because it captures continuously rather than when you remember to. It is a browser extension that records every page you visit while a case is open: the full HTML and resources, the URL, a UTC timestamp and a hash of the capture, into a local case file that is full-text searchable. That hash-at-capture-time is the evidentiary point — it is the same argument as the manifest pattern in Archiving & Evidence Preservation, applied automatically to everything you looked at including the pages that turned out not to matter.
Commercial, subscription, now owned by Maltego Technologies, with a 30-day trial that needs no card. There is no CLI and no API: this is a GUI tool and the workflow is the product.
1. Install the extension, open the desktop app, and create a case BEFORE you
start looking. Captures outside an open case are not recorded.
2. Set the case name to your case ID, not to the target's name. The case file
leaks the target's name to anyone who sees your screen or your backups.
3. Toggle capture ON. The extension icon state is the only indication; check it
after every browser restart, because a silent-off session is unrecoverable.
4. Add "selectors" — the names, handles, domains and phone numbers you are
tracking. Hunchly then highlights them on every page you visit and logs
which page each one appeared on. This is the feature people underuse: it
catches a name in a footer you would never have read.
5. Tag pages as you go. An untagged case file of 4,000 pages is a search index,
not a narrative.
6. Export: the case export carries the captured pages, the hashes, the timestamps
and the selector hit log. Export at milestones, not just at the end — the
case file is a single local database and a single local database can corrupt.
7. Storage choice matters. Local keeps everything on your machine; the hosted
option puts your captures and therefore your whole research pattern on
someone else's infrastructure. Pick deliberately and write down which.
What it does not do: a Hunchly capture is a record that you saw that content at that time, with no third-party attestation. It is excellent provenance for your own process and weak evidence against a determined challenge, which is why anything load-bearing still gets a public-archive capture and an independent timestamp. It also captures everything, including pages you visited by accident and pages containing other people’s personal data — treat the case file as sensitive material in its own right.
Obsidian or Logseq: the case vault
Local, plain-text, file-per-entity notes with links between them. The reason this beats a document
is that an investigation is a graph of entities, not a narrative, and the thing you need six weeks
in is “every note that mentions this phone number”. Obsidian suits entity-per-note work where the
links between people are the finding; Logseq’s daily journal and outliner suit chronology-heavy
work. Both store Markdown on disk, so the vault is greppable, diffable and git-able without the
application.
Structure the vault so that provenance cannot be separated from content:
case-2026-014/
00-question.md the question, the standard of proof, the stop condition
10-entities/
person-a-khan.md one file per entity, named by role not by guesswork
company-northgate.md
account-acct_f.md
20-raw/ collected artefacts, never edited
2026-10-04T0407Z-post123.warc.gz
2026-10-04T0407Z-post123.info.json
MANIFEST.sha256
30-findings/
f01-post-edited-after-upload.md
40-negative/
not-found.md every search that returned nothing, with the query
90-log.md append-only: what you did, when, from which identity
Every entity note carries its own provenance header, so a claim can never be read without its source:
---
entity: company-northgate
type: company
aliases: ["Northgate Ltd", "Northgate Limited", "northgate ltd"]
confidence: medium
first_seen: 2026-10-03
last_checked: 2026-10-04
---
## Established
- Registered number 09876543, UK. Source: Companies House API, retrieved
2026-10-04T04:07Z. Raw: `20-raw/ch-09876543.json` (sha256 4b1c8e...).
## Reported but unverified
- Described as "the trading arm" in the filing at para 17. Single source,
uncorroborated, author has an interest. Do not repeat as fact.
## Ruled out
- Not the same as Northgate Mining Ltd (number 07654321). Different officers,
different address, name similarity only. Checked 2026-10-04.
## Open
- Beneficial owner behind the BVI parent. UK PSC filing names the parent only.
The Ruled out section is the one people skip and the one that saves the investigation. An
explicitly rejected hypothesis stays rejected; an implicitly rejected one resurfaces in a month as
a half-remembered lead and sometimes as a published error.
Three cautions. Do not use wiki-style double-bracket links if the notes might ever be published or converted — they do not resolve outside the application, and a dead link in a published finding reads as sloppiness. Sync services put your entire research graph on third-party infrastructure, so if the vault syncs, know where to. And a vault is not an archive: the notes reference the artefacts, and the artefacts need their own hashes and timestamps.
The research account
A separate identity that touches targets, which you expect to lose. Platforms ban research accounts eventually — for scraping, for viewing too many profiles, for geographic inconsistency, for nothing at all — so build nothing on it you cannot walk away from, and never let it share anything with an account you care about.
There is no tool for this. There is a checklist, and the order matters:
BEFORE the account exists
[ ] Decide the persona's purpose. A plausible-but-empty account is more
suspicious than an obviously new one with a stated interest.
[ ] Email first, from a provider that does not require a phone number, and
never from the provider your real accounts use.
[ ] Phone number, if the platform demands one. A number you control and can
lose. Never your own; a reused number links the research account to you
permanently and silently, because platforms match on it across services.
[ ] Password manager entry with the case ID in the title, so the account is
findable and disposable as a unit.
WHEN the account exists
[ ] Separate browser profile at minimum, separate VM if the target is
competent. Never the same profile as anything personal — shared cookies,
shared localStorage and shared autofill all link them.
[ ] Consistent timezone, language and locale between the account's stated
location and the browser's. A profile claiming Lisbon from an en-GB
browser on UTC+0 is a detectable mismatch.
[ ] No contact import. Ever. One accidental contact sync hands the platform
your real address book and the platform hands the target "people you
may know".
[ ] Age the account before using it. A day-old account viewing 200 profiles
is a rate-limit and a ban; a two-month-old one is a user.
ONGOING
[ ] One account per investigation where the targets could plausibly compare
notes. Cross-contamination between cases is how one burn becomes three.
[ ] Log every target the account touched, so you can assess the damage when
it is eventually identified.
[ ] Expect it to be lost. Export anything you need from it as you go.
The legal and ethical line is not a technical question and the checklist does not answer it. Creating an account usually breaches a platform’s terms of service; in some jurisdictions and some employment contexts it does more than that, and a persona that actively deceives a person — rather than merely observing public content — is a different act from a passive research account. Know which one you are doing, get it authorised in writing if you are doing it for anyone but yourself, and note that nothing here makes impersonating a real person or organisation acceptable.
Isolation: a disposable VM
A compromise or a deanonymisation should cost you a throwaway machine rather than your real one and the identity attached to it. Containers and virtual machines are not interchangeable here: a container shares the host kernel and, with default settings, the host network identity, which makes it fine for running CLI tooling and wrong for browsing a hostile target. Browse from a VM.
# full VM, Ubuntu, disposable: multipass on macOS and Windows
multipass find # 26.04 is the current LTS alias
multipass launch lts --name research-014 --cpus 2 --memory 4G --disk 20G
multipass shell research-014
multipass stop research-014 && multipass delete research-014 --purge # gone
# or Lima, the same idea with a declarative YAML template.
# Note the locator form: `template:` — the older `template://` is deprecated as of Lima 2.0
limactl create --name=research-014 template:ubuntu-lts
limactl start research-014
limactl shell research-014
limactl delete --force research-014
# snapshot before you touch the target, so you can roll back to clean.
# multipass only snapshots a STOPPED instance, so stop it first
multipass stop research-014
multipass snapshot research-014 --name pre-target
multipass start research-014
# ...after the session, roll back
multipass stop research-014
multipass restore research-014.pre-target --destructive
# containers: correct for CLI tooling, with the network identity made explicit
docker run --rm -it \
--dns 1.1.1.1 \
--cap-drop ALL --security-opt no-new-privileges \
-v "$PWD/out:/out" \
python:3.13-slim bash
# route a container's traffic through a proxy you control, and nothing else
docker run --rm -it \
-e ALL_PROXY=socks5h://host.docker.internal:1080 \
-e HTTPS_PROXY=socks5h://host.docker.internal:1080 \
-v "$PWD/out:/out" python:3.13-slim bash
# a container that cannot reach the network at all, for handling a hostile file
docker run --rm -it --network none -v "$PWD/sample:/sample:ro" python:3.13-slim bash
# check the VM's egress before you use it, not after
multipass exec research-014 -- curl -s https://am.i.mullvad.net/json
For network-level rather than machine-level isolation, Whonix routes an entire VM’s traffic through Tor at the gateway, so a misconfigured application inside it cannot leak around the proxy, and Tails gives you an amnesic live system that forgets everything on shutdown. Both are the right answer when the consequence of being identified is serious; both are heavy enough that people skip them for routine work, which is a defensible trade as long as it is a decision rather than a default.
What isolation does not buy you: a clean VM behind a VPN is still identified by the account you log into, the browser fingerprint you present and the timing of your activity. Isolation limits the blast radius of a mistake. It does not make you anonymous.
Touching a target without leaking
When you need the bytes from a target’s own server rather than from an archive, go via the command
line rather than a browser, because a browser sends dozens of headers you did not choose and runs
code the target wrote. Here the honest version matters: neither curl nor wget has a
--no-referer flag, because neither sends a Referer header unless you ask it to. Verified, a
default curl request arrives at the server carrying only Host, User-Agent and Accept.
# exactly what a default curl sends — check this yourself rather than trusting it
curl -s https://postman-echo.com/headers | jq .
# {"headers":{"host":"postman-echo.com","user-agent":"curl/8.7.1","accept":"*/*", ...}}
# headers only, no body: cheapest possible look, and it reveals the stack
curl -sI 'https://target.example/page'
# response headers AND body, with the body discarded — some servers lie on HEAD
curl -s -o /dev/null -D - 'https://target.example/page'
# present a plausible browser UA. A default "curl/8.7.1" in a small site's log
# is a flag that says "someone is scripting against us"
curl -s -A 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
'https://target.example/page' -o page.html
# send no User-Agent at all, which is a different and sometimes better choice
curl -s -H 'User-Agent:' 'https://target.example/page' -o page.html
# a Referer only when you deliberately want the log to show a plausible path
curl -s -A 'Mozilla/5.0 ...' -e 'https://www.google.com/' 'https://target.example/page'
# show the redirect chain without following it into something you did not expect
curl -sIL -w '%{http_code} %{url_effective}\n' -o /dev/null 'https://target.example/short'
# through a SOCKS proxy, with DNS resolved AT the proxy — socks5h, not socks5
curl -s --proxy socks5h://127.0.0.1:9050 'https://target.example/page' -o page.html
# wget equivalents, for a recursive pull you want to keep polite
wget -U 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
--wait=2 --random-wait --limit-rate=200k \
--page-requisites --adjust-extension 'https://target.example/page'
socks5h versus socks5 is the one that bites people: with socks5, curl resolves the hostname
locally and only the TCP connection goes through the proxy, so your resolver — and therefore your
ISP and often your employer — sees exactly which host you looked up. With socks5h the proxy does
the resolution. The same distinction applies to ALL_PROXY in the container examples above.
Two things no flag fixes. The TLS handshake carries the hostname in SNI unless the server supports Encrypted Client Hello, so a passive observer on your network learns which site you contacted regardless of these options. And a target that fronts its site with a CDN sees your request through that CDN’s logging, which is a second party you did not choose.
Leak checks: IP, DNS and WebRTC
Run these before you touch a target, after every network change, and after every VPN reconnect. The failure you are looking for is not “am I behind a VPN” — it is “does something on this machine resolve or connect outside the tunnel”, which is invisible until you measure it.
# the address a web server sees
curl -s https://am.i.mullvad.net/json | jq '{ip, country, city, mullvad_exit_ip, organization}'
curl -s https://ifconfig.co/json | jq '{ip, country, asn_org}'
# the address your DNS RESOLVER egresses from — this is the leak that matters.
# If this is your ISP while the line above is a VPN exit, DNS is outside the tunnel.
dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
# resolver IP, your apparent client IP, and the EDNS Client Subnet your resolver
# is handing to authoritative servers. An "ecs" line means your /24 is being
# disclosed to every nameserver you query.
dig +short TXT whoami.ds.akahelp.net
# which resolvers this machine is actually using, whatever the VPN client claims
scutil --dns | grep nameserver # macOS
resolvectl status | grep -A2 'DNS Serv' # systemd-resolved
# does a hostname resolve the same inside and outside the isolated VM
dig +short target.example
multipass exec research-014 -- dig +short target.example
# mullvad's own CLI, if that is your provider: state, and whether DNS is leaking
mullvad status
mullvad dns get
WebRTC and browser fingerprinting have no CLI equivalent, because the leak is the browser’s and only a browser reproduces it:
https://browserleaks.com/webrtc does the browser disclose your real local
and public IP via ICE candidates, around
the proxy. This is the classic VPN leak and
it is a browser setting, not a network one.
https://browserleaks.com/dns which resolvers the browser actually used
https://www.dnsleaktest.com/ extended test; run it, not the standard one
https://coveryourtracks.eff.org/ how distinctive your fingerprint is. Read
the "one in N browsers" number, not the
pass/fail badge.
https://browserleaks.com/geo whether the page can get a precise location
from the OS rather than from the IP
Read the fingerprint result carefully, because the intuition is backwards: hardening a browser with unusual settings and a long extension list makes it more identifiable, not less. A stock browser in a stock VM is often the better disguise than a heavily customised one, and the only reliable counter to fingerprinting is to look like a large crowd.
What these checks cannot tell you: whether the target correlated your visit with something else. Timing, a reused screen resolution, the same unusual font set, a session that starts every weekday at 09:10 UTC — none of that shows up in a leak test, and all of it is linkable across identities.
Chain of custody
The record that lets you say, later, that the file you are producing is the file you received, and that nothing happened to it in between that you have not written down. It costs a minute per artefact and it is the first thing attacked when a finding matters.
# the moment an artefact arrives, before you open it
IN=~/cases/2026-014/20-raw
mkdir -p "$IN"
cp /Volumes/USB/clip.mp4 "$IN/" # copy, never move
shasum -a 256 "$IN/clip.mp4" | tee -a "$IN/MANIFEST.sha256"
chmod 444 "$IN/clip.mp4" # read-only: work on copies
# the custody note, as a sibling file, written now and never edited
cat > "$IN/clip.mp4.custody" <<'EOF'
artefact: clip.mp4
sha256: 4b1c8e... # from MANIFEST.sha256
received_at: 2026-10-04T04:07:56Z # date -u +%FT%TZ
received_from: source S-3 (see 10-entities/source-s3.md), in person, USB
provided_as: claimed original off a phone; no chain before this point
handled_by: J. Investigator
first_action: hashed, set read-only, copied to 50-work/ for analysis
onward: none
EOF
# every derived file records what it came from, so no copy is ever orphaned
shasum -a 256 50-work/clip-frame-0137.png >> 50-work/DERIVED.sha256
printf '%s\tderived from\t%s\n' 'clip-frame-0137.png' 'clip.mp4 (4b1c8e...)' \
>> 50-work/DERIVED.index
# append-only activity log, one line per action, in UTC
printf '%s\t%s\n' "$(date -u +%FT%TZ)" 'extracted frame 00:01:37.5 with ffmpeg 8.0' \
>> ~/cases/2026-014/90-log.md
# verify the whole raw tree before you hand anything over
shasum -a 256 -c "$IN/MANIFEST.sha256" | grep -v ': OK$'
Then timestamp the manifest, which is what converts your own record into a third party’s assertion
about time — ots stamp and the RFC 3161 route are in
Archiving & Evidence Preservation.
Four rules that are not negotiable. UTC everywhere, because a local timestamp in a report with international sources is ambiguous and ambiguity is attackable. Copy rather than move, so the original stays where it was. Write the note at the time, because a custody note reconstructed from memory is exactly as reliable as it sounds. And record the gap honestly: if you do not know where the file was before your source handed it to you, the note says “no chain before this point” rather than nothing, because an unstated gap reads as a concealed one.
The negative-results log
The cheapest high-value habit on this page, and the one almost nobody keeps. A searchable record of every query that returned nothing stops you repeating dead ends, tells you where your coverage actually ends, and is the only honest basis for a sentence like “no public record of X exists”.
# 40-negative/not-found.md — append-only, one block per attempt
## 2026-10-04T04:12Z — Companies House officer search
query: "Khan" + date of birth 1979-03
scope: all UK registered companies, active and dissolved
result: 0 matches with that DOB month
means: not registered as a UK officer under that spelling. Does NOT mean
not an officer: Companies House shows DOB month and year only, and
transliteration variants were not tested.
next: re-run via Bellingcat Name Variant Search for Cyrillic variants
## 2026-10-04T04:31Z — Sherlock, handle "acct_f"
query: sherlock acct_f --print-found
result: 3 hits, all confirmed unrelated third parties
means: handle is reused; it is not a usable pivot for this person
next: pivot on the profile photo instead, not the handle
## 2026-10-04T05:02Z — Wayback, target.example/about
query: CDX, matchType=prefix, from=20240101
result: no captures
means: nothing about absence of the page. The site serves a robots
directive that Wayback honoured at crawl time.
next: check archive.today and Ghostarchive before concluding anything
The means: line is the whole point and it is the line that gets dropped. “Zero results” is a fact
about a tool’s coverage, and turning it into a fact about the world is the single most common
overreach in open-source work. A people-search service returning nothing means that service has
nothing. A registry returning nothing means that registry, under that spelling, on that date.
Write the next: line too. A negative result with a stated next step is a lead; a negative result
without one is just a gap you will rediscover.
Verification
Treat every claim as unverified until it is pinned to something independent:
- Where — does the imagery match satellite, street view, terrain? Are the shadows consistent with the claimed time? See Geolocation.
- When — is the content older than the event it supposedly shows? Reverse image search first, every time. See Reverse Image Search.
- Who — does the account have history, or was it created last week? Do the same photos appear on other profiles under other names?
- What — is the file original, or a re-encode of a re-encode? See Image & Video Forensics.
Two sources that both trace back to the same original post are one source.
Note-taking and case management
| Tool | What it does | Cost |
|---|---|---|
| Hunchly | Browser extension that silently captures every page you visit during a case, with hashes and timestamps, and builds a searchable case file. | paid |
| Obsidian | Local markdown notes with backlinks. Good for entity-per-note investigations where the links between people matter as much as the people. | free |
| Logseq | Outliner-style local notes with daily journals. Suits chronology-heavy work. | free |
| Atlos | Purpose-built collaborative platform for visual investigations, with source tracking and multi-investigator review. | free |
Pitfalls
- Confirmation lock-in. Writing the conclusion first and collecting support for it. Ask what evidence would prove you wrong, then go look for that.
- Machine translation as fact. A mistranslated verb changes a claim. Check anything load-bearing with a speaker or a second engine.
- Automated tools as authority. Username enumerators, facial recognition and breach lookups all produce false positives. They generate leads, not findings.
- Losing the chain. If you cannot say where a file came from and when you got it, you cannot use it.
- Forgetting the human cost. Publishing that someone can be located has consequences for them. Minimise what you expose beyond what the finding requires.
- A VPN indicator is not a leak test. The client says “connected” while the system resolver still egresses from your ISP, and a browser can hand out your real address over WebRTC around any tunnel. Measure the resolver and the browser separately, after every reconnect.
socks5where you meantsocks5h. The proxy carries the connection but your own resolver does the lookup, so the hostname is logged locally even though the traffic was not.- Hardening a browser makes it more identifiable. An unusual configuration and a long extension list are a fingerprint. A stock browser in a disposable VM hides in a larger crowd.
- Zero results is a fact about a tool, not about the world. Record what the gap means and what it does not, in the same note, at the time.
Worked example
One datum: a tip-off email naming a company, Northgate Minerals Trading, and asserting it is a
front. Nothing else. The question is not “is it a front” — that is a conclusion looking for support.
This is the first hour, before any collection, and what it buys you.
# 1. write the question down. 00-question.md
question: Does any public record link Northgate Minerals Trading to
[named entity] through a shared officer, address or owner?
standard: two independent primary sources per link, or it is "reported, unverified"
out of scope: the tipster's motive; family members of any officer
stop when: the question is answered either way, or three named registries
have been checked and returned nothing
exposure: registry APIs and archives only. NO requests to any Northgate-
controlled domain from an attributable address until step 6.
The exposure line is the decision that constrains everything after it. Having written it down, the first four steps are forced: only sources that do not touch the target.
# 2. establish the egress before anything leaves the machine
curl -s https://am.i.mullvad.net/json | jq '{ip, country, organization, mullvad_exit_ip}'
dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
# web-visible IP: a VPN exit, country NL
# resolver egress: 203.0.113.x — the SAME ISP range as the host, not the VPN
DNS is outside the tunnel. Every hostname you look up is visible to the ISP, and will be whether or not the HTTP request goes through the VPN. Fix that before step 3, not after: the resolver leak is the one that persists, because it is a system setting and the VPN client reported “connected”.
# 3. isolation, and verify it from inside rather than trusting the launch
multipass launch lts --name research-014 --cpus 2 --memory 4G --disk 20G
multipass exec research-014 -- curl -s https://am.i.mullvad.net/json | jq -r .ip
multipass exec research-014 -- dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
# both now report the VPN exit. Snapshot clean before use:
multipass stop research-014 && multipass snapshot research-014 --name pre-target
multipass start research-014
# 4. open the Hunchly case BEFORE the first search, not after
case name: 2026-014 (the case ID, never "Northgate")
selectors: Northgate Minerals Trading
Northgate Ltd
09876543
[officer surname, once known]
capture: ON — confirmed by the extension icon after the browser restart
Every page from here on is captured, hashed and timestamped whether or not you thought it mattered at the time. That is the whole reason the case opens before the searching: the page you will need is the one you skimmed on the way to something else.
# 5. collect from sources that do not touch the target, and log the negatives
# (the registry and sanctions commands themselves live on the companies sheet)
printf '## %s — Companies House name search\nquery: "Northgate Minerals Trading"\nresult: 2 hits, gb/09876543 active + vg/1654321 (source dated 2019)\nmeans: a UK and a BVI company share the name. Not yet evidence they are related.\nnext: PSC filing on 09876543\n\n' \
"$(date -u +%FT%TZ)" >> ~/cases/2026-014/40-negative/not-found.md
# 6. the only step that touches the target, and only after deciding to
# headers first: it answers the hosting question without fetching the page
multipass exec research-014 -- \
curl -sI -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
'https://northgate-minerals.example/' | head -12
# Server: cloudflare → the origin IP is not in this response, and a CDN
# operator now has a log line for this request. Noted in 90-log.md.
A HEAD from a VM behind a VPN, with a browser UA, after an explicit decision — rather than a
browser tab opened reflexively in hour one from your own address. The difference costs ninety
seconds and is the difference between the target knowing and not knowing.
# 7. the artefacts, hashed and custody-noted at the moment they arrive
IN=~/cases/2026-014/20-raw; mkdir -p "$IN"
multipass transfer research-014:/home/ubuntu/ch-09876543.json "$IN/"
shasum -a 256 "$IN/ch-09876543.json" | tee -a "$IN/MANIFEST.sha256"
chmod 444 "$IN/ch-09876543.json"
printf '%s\t%s\n' "$(date -u +%FT%TZ)" 'retrieved CH filing 09876543 via API from research-014' \
>> ~/cases/2026-014/90-log.md
# 8. the entity note, written as three separate claims. 10-entities/company-northgate.md
Established: number 09876543, UK, active. Source: CH API, 2026-10-04T05:12Z,
raw ch-09876543.json (sha256 4b1c8e...).
Reported/unverified: "a front". Single source, the tipster, who has an interest.
Not repeated as fact anywhere else in the case.
Ruled out: not Northgate Mining Ltd (07654321) — different officers,
different address, name similarity only. Checked 2026-10-04.
Open: beneficial owner behind the BVI parent.
After an hour the case holds: a written question with a stop condition, a fixed and verified exposure posture, a continuous capture log, two registry records with hashes and custody notes, one explicitly rejected lookalike company, and a negative-results entry that says what “two hits” does and does not mean.
What you can assert: which sources were queried, from which exposure posture, what they returned, and that the preserved registry artefacts still match the hashes recorded at acquisition. This is an auditable collection record, not a finding that the tipster’s allegation is true.
What none of that establishes: whether Northgate is a front. The tipster’s claim is still exactly one uncorroborated assertion, recorded as such, in a section of the note that cannot be mistaken for a finding. The substantive work now moves to Company & Financial Records — but it moves there on top of a record that will survive someone attacking it, which is the only thing this sheet is for.
What would falsify it: an exposure check showing traffic left by the host rather than the research VM, a gap in the action log, or a hash mismatch on either source artefact. Those failures do not prove the allegation false; they make the collection record too weak to support later claims.
Broader catalogues
More tools
Further tools for this area from the OSINT Newsletter Tools Library (Foundational OSINT Tools, Language Translation OSINT), excluding those already listed above.
| Tool | What it does |
|---|---|
| 100 Search Engines | A simple search hub that brings multiple search engines and specialist search services into one place. |
| 2lingual Search | A specialist search engine that lets investigators search the web in one language and discover results in another. |
| 527 Explorer | A ProPublica database that lets you track political “527” organisations in the US i.e. groups that raise and spend money to… |
| Apertium | An open-source rule-based machine translation platform. |
| Authentic8 Silo Workspace | A secure, cloud-native browser designed for conducting online investigations safely, anonymously, and at scale. |
| Babylon | Multilingual dictionary and translation tool. |
| Copyleaks | AI-powered plagiarism and AI-content detection platform that compares text against web pages, academic sources and proprietary… |
| Cover Your Tracks | A privacy-testing tool from the Electronic Frontier Foundation that checks how identifiable your browser and device are online. |
| DeepL Translator | Online translation tool that converts text from one language to another. |
| DuckDuckGo | A privacy-focused internet search engine and web browser. |
| EarthPoint Convert | A web-based conversion tool for transforming geographic coordinate data between formats. |
| Excite Web Search | A general-purpose internet search service to search for publicly available webpages and online information using keywords, names… |
| Fagan Finder | A comprehensive search portal that brings together hundreds of search engines, specialist databases, and online resources in one… |
| FindTheScam | Checks whether a website looks legitimate or risky by reviewing WHOIS age, HTTPS/SSL, DNS, reputation, and scam-warning signals. |
| Finger Printer | An interactive browser fingerprinting dashboard that generates and displays a range of unique identifiers based on the behaviour… |
| Forensic OSINT | A digital evidence capture and preservation platform to collect, document, and preserve online content. |
| FreeSubtitles AI | AI-powered transcription and subtitle generation tool that converts audio and video files into text and subtitles, with… |
| GetProofAnchor | A web-based tool that captures and preserves online content as verifiable digital evidence. |
| Human or AI | A game-style OSINT training tool that challenges you to spot the difference between real human profile photos and AI-generated… |
| Known Agents | A directory of AI bots and the associated information it has on each bot. |
| Maltego | A visual link analysis and OSINT platform to discover, map, & understand relationships between people, organisations, domains… |
| OpenGraph Intel | A self-hosted OSINT and link analysis platform that enables investigators to collect, enrich, visualise, and analyse… |
| OSINTracker | A browser-based OSINT investigation management platform that helps organise entities, map relationships, visualise connections… |
| Palette by OSINT Industries | A powerful graph visualisation platform with integrated native search for mapping and analysing OSINT data relationships. |
| SIERRA | A local-first desktop investigation workspace for organizing evidence, entities, notes, timelines, and tool output in one case… |
| Ubikron | An OSINT investigation workbench that transforms your browser into a structured intelligence collection and analysis platform. |
| Your social media fingerprint | An OSINT awareness tool showing how much personal and behavioural data can be “leaked” from social media activity to understand… |
Sources
Both catalogues below are maintained by other people and are considerably larger than this page. Use them as the canonical index; this sheet is a working route through them.
- Bellingcat’s Online Investigation Toolkit — ~340 tools, each with its own review page covering cost, difficulty, requirements and limitations.
- OSINT Newsletter Tools Library — ~280 tools, organised by investigative goal.
Neither publishes a licence, so nothing here is copied from them: tool names, one-line descriptions, cost flags and links are catalogue facts, and the method and commentary are this site’s own. See credits.