Fast username hunter written in Go. Hunt across 400+ sites in parallel to find accounts tied to a given username.
- Wide coverage: 400+ sites.
- Fast: concurrent HTTP checks, configurable parallelism.
- Multi-target: search several usernames in one run, positional or from a file.
- Flexible output: text, JSON, CSV, or Markdown.
- Exclusion lists: skip sites inline or from a file (
-exclude @list.txt). - NSFW filter: opt out with
-no-nsfw. - Robust: retries on transient failures (5xx, 429, network errors).
- Zero deps: a single static binary.
go install github.com/anderson3x11/hermes@latest
Or clone and build:
git clone https://github.com/anderson3x11/hermes.git
cd hermes
go build .
hermes username
hermes user1 user2 user3
hermes -file users.txt
hermes -file users.txt username
hermes -file users.txt user1 user2
One username per line, blank lines and comments are ignored, duplicates are deduplicated. You can combine -file and usernames, in this case the usernames are checked first, then the file.
hermes -exclude GitHub,Twitter username
hermes -exclude @ignore.txt username
hermes -exclude GitHub,@ignore.txt,Reddit username
hermes -o results.txt username
hermes -csv -o results.csv username
hermes -json -o results.json -file users.txt
hermes -md -o report.md username
| Flag | Default | Description |
|---|---|---|
-c |
20 |
Concurrent requests |
-t |
10s |
Request timeout |
-retries |
2 |
Retries on transient errors (5xx, 429, network) |
-v |
false |
Verbose — show errors and not-found |
-file |
— | Read additional usernames from file (one per line, # comments) |
-exclude |
— | Comma-separated site names to skip; @path reads names from a file |
-no-nsfw |
false |
Skip sites tagged NSFW |
-json |
false |
Emit results as JSON |
-csv |
false |
Emit results as CSV (all rows: site,username,found,url,error) |
-md |
false |
Emit results as a markdown table (hits only) |
-o |
— | Write output to file instead of stdout |
-json, -csv, and -md are mutually exclusive.
[
{
"username": "username",
"results": [
{ "site": "GitHub", "url": "https://www.github.com/username", "found": true },
{ "site": "Keybase", "url": "https://keybase.io/username", "found": false },
{ "site": "SomeSite", "url": "https://somesite.com/username", "found": false, "error": "context deadline exceeded" }
],
"summary": { "found": 108, "errored": 24, "skipped": 2, "nsfw_filtered": 0, "total": 434 }
}
]One row per site check across all users, including not-found and errored rows:
site,username,found,url,error
GitHub,user,true,https://www.github.com/user,
SomeSite,user,false,https://somesite.com/user,context deadline exceeded
A hits-only table (great for reports):
| Site | Username | URL |
|------|----------|-----|
| GitHub | user | https://www.github.com/user |
- The Go standard
flagpackage stops parsing at the first positional argument. Always put the names last:hermes -c 40 user1 user2, nothermes user1 user2 -c 40.
Several high-profile sites (e.g Twitter/X, Instagram, LinkedIn, Discord...) currently return unreliable results due to anti-bot measures on the real sites and dead third-party mirrors in the inherited site list. They are silently skipped or show as errors in a normal run, so they don't clutter the output, but if one of them is consistently missing for an account you know exists, this is expected. See BROKEN_SITES.md for the per-site details and manual-check URLs.
Inspired by and seeded with the site list from the Sherlock Project.
