Detection
How the risk engine scores, how profiles and policies apply, and what happens under attack.
On this page
Adaptive Risk Engine
The risk score is the weighted sum of all penalties (0-100). Thresholds are determined by the active site profile and form policy. The V2 response additionally includes a confidence score (0.0-1.0) and machine-readable reason codes.
| Score | Action | Meaning |
|---|---|---|
| 0-29 | allow | Human, allow |
| 30-59 | challenge | Suspicious, allowed through but logged |
| 60-100 | block | Bot detected, block |
Penalty factors
pow_failed: +100 PoW falsch oder fehlend nonce_reused: +100 Replay-Angriff ip_blocked: +100 IP auf Blockliste rate_limit_hit: +80 Zu viele Requests user_agent_headless: +70 Puppeteer/Playwright tor_exit: +60 TOR Exit Node behavior_bot: +50 Verhalten bot-typisch time_too_fast: +35 Submit < 1.5 Sekunden asn_hosting: +25 Rechenzentrum-ASN behavior_suspicious: +20 Verhalten verdächtig
V2.1 Advanced Bot Detection
Additional signals that expose even disguised headless browsers. All checks are context-aware: mobile devices and privacy browsers (Safari/Firefox) are correctly recognized as legitimate and not falsely flagged.
env_automation_globals: +90 Selenium/Puppeteer/CDP Leak im window-Objekt env_ua_brand_bot: +80 UA Client Hints verraten Automation-Framework env_software_renderer: +50 WebGL nutzt SwiftShader/llvmpipe = headless env_canvas_too_fast: +40 Canvas-Render < 2ms = headless (Mensch: 5-50ms) env_no_storage: +30 localStorage UND indexedDB fehlen env_raf_robotic: +25 requestAnimationFrame perfekt uniform (CV < 0.05) env_no_webgl_ext: +25 0 WebGL-Extensions auf Desktop = headless header_no_sec_fetch: +25 Sec-Fetch-* Header fehlen = altes/scripted Client header_no_accept_lang: +20 Accept-Language fehlt = scripted env_no_hover: +5 Hover nicht unterstützt (selten valide auf Desktop) env_audio_hash_missing: +5 OfflineAudioContext blockiert (Privacy-Browser ok)
V2.1 significantly increases the detection rate of stealth frameworks (Playwright Stealth, Puppeteer Stealth) without affecting legitimate users.
Site profiles & form policies
The V2 Risk Engine scores in context: login forms are judged more strictly than contact forms. Site profiles define the baseline, form policies override it per form type.
Site profiles (presets)
Every site is assigned a profile. The profile determines thresholds, challenge types and behavioral weightings.
| Profile | Allow < | Challenge < | Difficulty | Use case |
|---|---|---|---|---|
| Low Friction | 40 | 70 | 2 | Newsletter, comments, info pages |
| Balanced | 30 | 60 | 4 | Default for most forms |
| Auth Hardened | 20 | 50 | 5 | Login, registration, password reset |
| High Security | 15 | 40 | 6 | Checkout, admin actions, payment |
Form policies
Form policies override the site profile for specific form types. The form_type is sent along with the verify request.
| form_type | Profile | Allow < | Challenge < | Fail mode |
|---|---|---|---|---|
| login | Auth Hardened | 20 | 50 | fail_closed |
| register | Auth Hardened | 20 | 50 | fail_closed |
| password_reset | High Security | 15 | 40 | fail_closed |
| checkout | High Security | 15 | 40 | fail_closed |
| contact | Balanced | 30 | 60 | fail_open |
| comment | Low Friction | 35 | 65 | fail_open |
| newsletter | Low Friction | 40 | 70 | fail_open |
Merge order
Later levels override earlier ones:
1. Globale Defaults (config: allow<30, challenge<60) 2. Site-Profil (z.B. "Auth Hardened" → allow<20, challenge<50) 3. Form-Policy (z.B. login → allow<15, fail_closed)
Integration (developers)
The form_type is specified when embedding the widget and in the verify request:
<!-- Widget: form_type als data-Attribut --> <form data-captchacore="interactive" data-form-type="login"> <div data-captchacore-widget data-form-type="login"></div> </form> // Verify-Request: form_type im Body POST /api/v2/verify { "token": "...", "form_type": "login" // Steuert welche Policy angewendet wird }
Available types: login, register, contact, comment, checkout, password_reset, newsletter, custom. Without form_type, the global defaults are used.
Under-Attack-Mode
During an attack (high block rate), protection can be tightened:
Automatic activation
If more than 70% of all requests are blocked within a 5-minute window, UAM activates automatically.
# Konfigurierbar in den globalen Einstellungen uam.auto_threshold: 0.70 # 70% Block-Rate uam.window_minutes: 5 uam.auto_deactivate_after: 3600 # 1 Stunde uam.cookie_ttl_minutes: 30
In UAM, PoW difficulty increases by +1 level. Verified visitors receive an HMAC-signed access cookie (HttpOnly, SameSite=Strict).