No black box. Every point the scanner gives is earned from one of five checks below, and the API that runs them is open to call directly.
Every point is earned from one of five checks, and the weighting below is exactly what the code runs.
| Check | What it looks for | Weight |
|---|---|---|
| Reachability | Live response, HTTP status in the 200–399 range, within a 10s timeout | 20 pt |
| Stayed on domain | The link didn't redirect to a different domain than the one submitted — catches links that forward to an unrelated, legitimate site to borrow its score | 20 pt |
| HTTPS | Page is served over a valid encrypted connection | 10 pt |
| Not parked | No match against known registrar parking-page signatures (GoDaddy, Sedo, etc.) | 20 pt |
| Real content | Visible text length, minus "coming soon" / placeholder patterns | 15 pt |
| Internal links | Number of links pointing back into the same site | 15 pt |
Score bands: 75–100 = SIGNAL · 45–74 = MIXED · 15–44 = WEAK · 0–14 = VAPOR
If the link redirects to a different domain than the one submitted, the score is capped at 35 regardless of how the destination page checks out — redirecting to an unrelated, legitimate site to borrow its score is a known trick, not a loophole.
The same endpoint the live scanner calls is open for you to hit directly — no key, no auth, nothing stored.
| Endpoint | Method | Params |
|---|---|---|
| /api/scan | GET | url (required) |
Example request
curl "https://vaporscanrbh.xyz/api/scan?url=https://example.com"
Example response
{
"url": "https://example.com",
"score": 80,
"verdict": "SIGNAL (80/100) -- looks like a real, functioning site. ...",
"rows": [
{ "title": "Reachable", "detail": "The site responded successfully (HTTP 200) in 340ms...", "points": 20 },
{ "title": "Stayed on the declared domain", "detail": "The link didn't redirect anywhere unexpected...", "points": 20 },
{ "title": "Served over HTTPS", "detail": "The connection is encrypted...", "points": 10 },
{ "title": "No parked-domain signature", "detail": "The page doesn't match any of the known templates...", "points": 20 },
{ "title": "Content depth", "detail": "There's substantial written content on the page...", "points": 15 },
{ "title": "Internal links", "detail": "The page has 11 links pointing to other pages...", "points": 0 }
]
}
The whole app is three small files — server.js, scanner.js,
public/index.html — with zero external dependencies beyond Node itself.
Clone it, run node server.js, done. Full breakdown of the architecture
and why it's built this way is in the project's README.md.