Detection Signals
Each signal is evaluated independently. When a signal fires, its point value is added to the Trust Score. The Details array in the webhook contains every signal that fired for that session.
Device Signals (OS Fingerprinting)
ShieldLabs compares the User-Agent OS against the TCP stack fingerprint (TTL, MSS, window size). Anti-detect browsers change the User-Agent but cannot fake the TCP stack of the underlying OS.
| Signal | Points | When it fires |
|---|
UA OS is not detected | +30 | Cannot determine OS from User-Agent (e.g. HeadlessChrome, empty UA) |
Network OS is not detected | +30 | TCP fingerprint did not match any known OS |
Fail by windows os detect | +30 | UA says Windows, TCP says it’s not Windows |
Fail by linux os detect | +30 | UA says Linux, TCP says it’s not Linux |
Fail by android os detect | +30 | UA says Android, TCP says it’s not Android |
Fail by IOS detect | +30 | UA says iOS, TCP says it’s not iOS (or macOS) |
Fail by Mac OS detect | +30 | UA says macOS, TCP says it’s not macOS (or iOS) |
iOS and macOS share the same TCP stack — Fail by IOS detect and Fail by Mac OS detect account for this. Spoofing macOS on Linux will trigger Fail by Mac OS detect.
OS mismatch scenarios
| Scenario | User-Agent | TCP | Signal |
|---|
| Clean Windows user | Windows | Windows | ✅ No signal |
| Clean Mac user | macOS | macOS | ✅ No signal |
| ADS on Windows with Mac UA | macOS | Windows | Fail by Mac OS detect +30 |
| ADS on Linux with Windows UA | Windows | Linux | Fail by windows os detect +30 |
| Headless browser | Unknown/HeadlessChrome | Unknown | UA OS not detected +30, Network OS not detected +30 |
Network Signals (IP Intelligence)
Sourced from ipapi.is — real-time ASN, VPN, proxy, and abuse intelligence.
| Signal | Points | Description |
|---|
Is VPN | +10 | IP belongs to a known VPN provider (not yet confirmed by STUN) |
Is vpn by base ip | +15 | VPN confirmed by IP base (override-eligible — see Override Rules) |
Is vpn by network & by base ip | +15 | VPN confirmed by both network analysis and IP base |
Is proxy | +30 | IP is a proxy server |
Is datacenter | +20 | IP is from a cloud/datacenter ASN (AWS, GCP, DO, etc.) |
Is abuser | +20 | IP is in abuse blacklists (spam, DDoS, scraping) |
Is tor | +15 | Tor exit node |
Connectivity Signals (STUN/ICE)
ShieldLabs uses WebRTC STUN to detect the real IP and confirm UDP connectivity. Bots and headless browsers often cannot complete STUN.
| Signal | Points | Description |
|---|
Stun is not checked | +30 | UDP blocked or WebRTC disabled — STUN did not complete |
Browser timezone ≠ IP-timezone | +10 | Browser’s Intl.DateTimeFormat timezone doesn’t match the IP’s geolocation timezone |
How signals combine
Example: Anti-detect browser with VPN on Windows (UA says macOS)
Is vpn by base ip: +15 (VPN)
Fail by Mac OS detect: +30 (UA=macOS, TCP=Windows)
Stun is not checked: +30 (UDP blocked)
──────────────────────────────
Raw total: 75
After override rules: 70 (see /concepts/rules)
Reading the Details array
In the webhook payload, Details is an array of all signals that fired:
"Details": [
{ "Value": 20, "Description": "Is datacenter" },
{ "Value": 30, "Description": "Stun is not checked" },
{ "Value": 10, "Description": "Browser timezone ≠ IP-timezone" }
]
The sum of all Value fields equals the Score (after override rules are applied).