How detection works
Most username checkers decide by the HTTP status: 200 means the profile exists, 404 means it does not. Many sites answer 200 for everything, show a "user not found" page with a 200, or redirect to a login page, so a status check alone fills a report with false hits. Aliens Eye reads the page itself.
#Reading the page
Each response becomes a 30-number feature vector:
- HTTP: the status bucket (200, 3xx, 4xx, 5xx), the number of redirects, and whether the request was sent to a login or sign-up path.
- The username: whether it appears in the final URL's path, the title, the meta description or the canonical link.
- Words: counts of profile words ("followers", "joined", "member since") and error words ("not found", "doesn't exist", "no such user"), in the content and the meta tags, in several languages.
- Page shape: images, forms and inputs, and CSS classes that look like a profile or an error.
- Structured data: an OpenGraph type of
profile, a JSON-LDPerson. - Timing and size: response time and content length.
- Fingerprints: how closely the page matches pages from earlier scans of the same site (see below).
#Two judges
- Heuristics: a weighted score over the features, squashed into a probability.
- ML model: a logistic regression trained on labelled scans of real and made-up
accounts. It ships with the package as plain numbers in
model.jsonand runs as a dot product in pure Python, so scanning needs no scikit-learn or NumPy.
The two are blended into one probability, and the probability into a verdict. The model file sets the blend and the thresholds:
| ML weight | Found above | Not Found below | |
|---|---|---|---|
| Shipped model (the default) | 0.9 | 0.620 | 0.360 |
No model loaded (--no-ml, missing or invalid file) |
0.4 | 0.60 | 0.35 |
Between the thresholds the result is Maybe. Confidence grows with the distance from the threshold.
#Site rules
Most entries in the extended catalog carry a rule from their source database: the status a missing profile returns, text that appears only on a real profile or only on an error page, the address a missing profile redirects to, or a separate API address to ask. Where a rule exists, its evidence is combined with the detector's: when they disagree, or the markers conflict, the result stays Maybe.
For a JSON API probe, a Found needs the answer to name the username explicitly and the rule to agree. The HTML model is not presented as a judge of JSON.
#Checks on every Found
A page is scored on how profile-like it looks, and error pages, challenge pages and empty JavaScript shells can look the part. So a Found has to survive three checks:
- The HTTP status. 404 and 410 mean Not Found. A status that means the site is refusing or failing rather than answering (401, 403, 407, 408, 419, 420, 425, 429, 451, 499, 999, any 5xx) is Maybe at most: it is a block page, not the site's "no such user" page.
- Bot checks. A CAPTCHA, a Cloudflare challenge or a similar error page is Maybe at most.
- The control check. The site is also asked for a random username that cannot
exist. If it answers with the same page, the site shows that page for anyone, and
the result drops to Maybe. This costs one extra request per Found;
--no-control-checkskips it, at the price of more false hits.
#Fingerprints
For each site, Aliens Eye remembers compact signatures of pages it has judged Found
and Not Found: a hash of the title, a hash of the meta tags, the shape of the DOM and
the Server header. On later scans, how closely a page matches each set becomes a
feature. The store lives in the platform cache directory, keeps up to 50 signatures
per site and label, and is shared by the command line and the library.
#When a page needs JavaScript
Some sites send an empty shell and draw the profile with JavaScript. With
--playwright (and the browser extra), a Maybe result is opened in headless
Chromium, the rendered page is read again, and the verdict can move. Only Maybe
results are rendered, so it costs little on most scans.
#Profile details
For each Found and Maybe, Aliens Eye pulls the display name, bio and avatar from the page: from OpenGraph and JSON-LD where the site provides them, otherwise from per-site selectors. These feed correlation, watch mode's profile alerts and the reports.
#Being polite to sites
- Requests to the same site are spaced at least
rate_limit_delayapart (0.2 s). - Failures that are worth retrying (timeouts, 408, 429, 5xx) are retried with
exponential backoff and jitter, honouring
Retry-Afterup to a cap. - Only the first 100 kB of a page is parsed (
max_content_bytes).
#Seeing it for one site
--explain prints all of this for each verdict: the HTTP response, each judge's
score and threshold, the site rule, the control check and the browser fallback.
aliens_eye someone --site github --explainHow well it works, measured: Accuracy.