Detection runner and probes¶
Botonomus ships two kinds of evidence about what a page can see: a local probe that compares a Botonomus launch with an ordinary one, and a detection runner that visits public bot-detection pages. Both describe one machine, network, browser build and date. Neither proves that a session is undetectable.
Public detection pages: botonomus detect¶
botonomus detect --runs 3
botonomus detect --sites sannysoft deviceandbrowserinfo --runs 5 --driver patchright
botonomus detect --proxy socks5://user:pass@proxy.example:1080 --json
Warning
detect contacts third-party websites. Run it deliberately, not in CI.
Built-in sites, in default order:
| Name | Page | What it reports |
|---|---|---|
deviceandbrowserinfo |
deviceandbrowserinfo.com/are_you_a_bot | Bot/human statement and the true flags behind it |
sannysoft |
bot.sannysoft.com | Classic headless and webdriver property table |
browserscan |
browserscan.net/bot-detection | Bot detection summary (Normal / Robot) |
fingerprint |
demo.fingerprint.com/web-scraping | Fingerprint Pro bot and tampering decision |
fingerprint-playground |
demo.fingerprint.com/playground | Smart Signals: tampering, anti-detect browser, suspect score, ML scores |
creepjs |
abrahamjuliot.github.io/creepjs | Headless, like-headless and stealth percentages (fail when headless or stealth > 0 %) |
incolumitas |
bot.incolumitas.com | OK/FAIL test tables; the spec-level WEBDRIVER row, which stock Chrome also fails, is ignored |
nowsecure |
nowsecure.nl | Cloudflare challenge page |
recaptcha-score |
antcpt.com/score_detector | reCAPTCHA v3 score (pass >= 0.7, fail <= 0.3) |
pixelscan |
pixelscan.net/fingerprint-check | Fingerprint consistency and masking |
fingerprint-scan |
fingerprint-scan.com | Bot score out of 100 (pass <= 30, fail >= 60) |
rebrowser |
bot-detector.rebrowser.net | Automation leak tests; any red row fails |
turnstile |
nopecha.com/demo/turnstile | Cloudflare Turnstile demo |
apivoid |
apivoid.com/tools/bot-detection-test | Server-side risk score and tampering verdict (pass <= 30, fail >= 70) |
donutbrowser |
donutbrowser.com/tools/bot-detection | Automation and spoofing checks, bot score out of 100 |
cleantalk |
cleantalk.org/am-i-a-bot | Human score out of 100 (pass >= 80, fail < 50) |
pixelscan-bot |
pixelscan.net/bot-check | Navigator, webdriver, CDP and user-agent checks |
recaptcha-google |
recaptcha-demo.appspot.com | Google's reCAPTCHA v3 demo score (pass >= 0.7, fail <= 0.3) |
recaptcha-2captcha |
2captcha.com/demo/recaptcha-v3 | reCAPTCHA v3 score after clicking Check |
turnstile-capskip |
capskip.com Turnstile demo | Cloudflare Turnstile widget verification |
Pages that compute their result on demand set DetectionSite(click_button="..."): the runner clicks that button (trusted input) after loading and before waiting for ready.
How a run works:
- Each site is visited
--runstimes, one run after another; different sites run concurrently up to--parallel(default 2). - Each run uses a fresh profile unless
--reuse-profileskeeps one profile per site. - After loading, the runner moves and scrolls with
Human(skip with--no-interact), waits for the page's result, and captures a screenshot and page text. - Verdicts come only from per-site extractor scripts. Results an extractor cannot decide are recorded as
unknown; nothing is inferred. A rate-limit page or challenge interstitial isblockedand counts neither as a pass nor as a failure (see Measuring). - Failures are categorised (timeouts, navigation, startup, ...) and never stop the other runs.
Output goes to artifacts/detection/<UTC time>/ (or --output): screenshots, page text, and report.json with per-run verdicts and details, per-site pass/fail/blocked/unknown/error counts and pass rate, error categories, and the environment: capture date, OS, executable name and SHA-256, Browser.getVersion product, driver, Botonomus version and proxy scheme only.
Note
The environment's executable name and SHA-256 are resolved from --executable or, when it is omitted, from the discovered Google Chrome. If Botonomus Chromium is installed, sessions may launch it under the default browser="auto" while the report hashes Chrome. Pass --executable explicitly when the hash matters; browser_product always comes from the running browser.
Every result in the README was produced this way. To reproduce it on your setup, run botonomus detect with the same driver and browser and compare the reports.
Your own detection pages¶
import asyncio
from pathlib import Path
from botonomus import Botonomus, BrowserConfig
from botonomus.diagnostics import SITES, DetectionSite, run_detection
MY_SITE = DetectionSite(
"my-check",
"https://deviceandbrowserinfo.com/are_you_a_bot",
ready="document.body.innerText.includes('You are')",
extractor="""() => {
const text = document.body.innerText;
if (text.includes('You are human')) return {verdict: 'pass', details: {}};
if (text.includes('You are a bot')) return {verdict: 'fail', details: {}};
return {verdict: 'unknown', details: {}};
}""",
)
async def main() -> None:
output = Path("artifacts/detection/example")
config = BrowserConfig(profile_root=output / "profiles")
async with Botonomus(max_instances=2, config=config) as bot:
report = await run_detection(bot, [SITES["sannysoft"], MY_SITE], runs=2, output=output)
for site in report.sites:
print(f"{site.site}: {site.passed}/{site.runs} pass, {site.errors} errors")
asyncio.run(main())
ready is a JavaScript expression polled until truthy; extractor is a function that returns {"verdict": "pass" | "fail" | "unknown", "details": {...}}. Both run in the isolated world with the native and Patchright drivers. Any other return shape is recorded as unknown. This example is examples/detection_sites.py in the repository.
Local probe: botonomus probe¶
The probe serves a local page that records automation-relevant observations: navigator.webdriver, CDP console serialization side effects, window.chrome, injected cdc_ or Playwright globals, plugins, notification-permission consistency, Client Hints, the WebGL renderer and window chrome size.
botonomus probe # Botonomus launch only
botonomus probe --normal --output artifacts/comparison
botonomus probe --serve # serve the page for a manual baseline
botonomus probe --baseline manual-browser.json
--normalfirst launches an ordinary browser without a debugging connection and collects the page's own report, then runs the identical page in Botonomus and compares every field. The baseline is a subprocess launch, not a claim that a human navigated. Files:automated.json,baseline.json,comparison.jsonunder--output;--jsonprints them instead.--serveprints a launch command; open the page yourself, download the JSON with the page's button, then compare with--baseline.- Diagnostic profiles are temporary.
Reading results honestly¶
- Some checks fail for ordinary Chrome too. The legacy incolumitas
WEBDRIVERtest flags'webdriver' in navigator, which is true in every current Chrome. - reCAPTCHA v3 scores mainly reflect IP reputation and profile history. In the published measurement, ordinary Chrome without automation scored 0.1 on the same IP and fresh profile.
- A clean report on one date says nothing about a site's next deployment. Re-run after browser updates.