Smart Signals are server-side enrichment signals computed from browser fingerprints, IP intelligence, and behavioral analysis. They provide deep context about every visitor without collecting any personally identifiable information.
Smart Signals — the enriched decision, risk, network, and bot signals — are delivered via webhooks (see Webhooks) and surfaced in the dashboard. The corresponding fields (decision, risk_score, network flags, bot_score, etc.) are present in the flat read-API event (see Server API Reference) too, but the read query does not populate them — they serialize as their zero/empty values there. The meaningful, enriched values arrive via the webhook payload, whose shape the examples below consume.
| Signal | Description | Response | Platform |
|---|---|---|---|
| VPN Detection | Detects VPN usage via timezone mismatch, ASN matching, relay detection, and TURN probe | network.vpn: boolean | Web, Mobile |
| Proxy Detection | Identifies datacenter and residential proxy usage | network.proxy: boolean | Web, Mobile |
| Tor Detection | Matches IP against known Tor exit nodes | network.tor: boolean | Web, Mobile |
| Datacenter | Flags IPs belonging to known cloud/hosting providers | network.datacenter: boolean | Web, Mobile |
| IP Geolocation | City-level geolocation from IP address | geo.{ country, city, lat, lon, timezone, isp } | Web, Mobile |
| Signal | Description | Response | Platform |
|---|---|---|---|
| Virtual Machine | Detects VMware, VirtualBox, Parallels, QEMU, Hyper-V | { result: boolean } | Web |
| Emulator | Detects mobile emulators (BlueStacks, Genymotion, Android SDK) | { result: boolean } | Web (mobile UA) |
| Root Detection | Detects rooted Android devices via UA and signal analysis | { result: boolean } | Web (Android) |
| Jailbreak Detection | Detects jailbroken iOS devices via screen analysis and UA | { result: boolean } | Web (iOS) |
| Cloned App | Detects dual-space/cloned app environments | { result: boolean } | Web (mobile) |
| Factory Reset | Identifies devices that have been factory reset | { result: boolean, timestamp?: string } | Web |
| Signal | Description | Response | Platform |
|---|---|---|---|
| Incognito Detection | Infers private browsing via multi-signal correlation | { result: boolean } | Web |
| Browser Tampering | Detects spoofed User-Agent, modified navigator, extension injection | { result: boolean, anomalyScore: number } | Web |
| Developer Tools | Detects when browser DevTools is open | { result: boolean } | Web |
| Privacy Settings | Detects privacy-focused browser configurations (Brave shields, Firefox ETP, Safari ITP) | { result: boolean } | Web |
| Frida Detection | Detects Frida instrumentation toolkit | { result: boolean } | Web (mobile) |
| Signal | Description | Response | Platform |
|---|---|---|---|
| Bot Detection | Identifies automation frameworks and headless browsers | bot.result: "human"|"bot"|"uncertain", bot.type: string, bot.score: number | Web, Mobile |
| Risk Score | Aggregated risk for the request, on the webhook decision object | decision.riskScore: number, decision.suspectScore: number, decision.action: string | Web, Mobile |
TRACIO detects VPN usage through four independent methods:
Timezone Mismatch: Compares the device timezone (from JavaScript Intl.DateTimeFormat) against the GeoIP timezone. A mismatch indicates the user's network traffic is routed through a different geographic location than their device.
Public VPN ASN: Matches the visitor's IP against a database of 42+ known VPN provider ASNs (NordVPN, ExpressVPN, Mullvad, ProtonVPN, etc.).
Relay Detection: Identifies anonymizing relay services including Apple iCloud Private Relay and Cloudflare WARP.
TURN Probe: Uses a WebRTC TURN server to discover the visitor's real IP address. If the TURN-detected IP differs from the HTTP request IP, VPN/proxy usage is confirmed.
These four methods are internal inputs. The public webhook payload surfaces the
combined result as a single boolean, network.vpn — there is no per-method
breakdown or confidence string in the delivered payload.
Incognito/private browsing is inferred server-side by correlating multiple signals:
navigator.storage.getDirectory() behavior changes in incognitoNo single signal is conclusive. The server requires correlation across 2+ signals to flag incognito mode.
The tampering detector identifies visitors who have modified their browser to misrepresent their identity:
navigator properties by comparing getter prototypesPluginArray.prototype and MimeType.prototype chainsFunction.prototype.toString, Object.getOwnPropertyDescriptor, and other critical functions have been replaced with ProxiesThe anomalyScore (0.0-1.0) quantifies the degree of inconsistency. Values above 0.5 indicate significant tampering.
The webhook decision object carries the aggregated risk for a request:
decision.riskScore (integer 0-100), decision.suspectScore (number), and
decision.action (the recommended action). The score aggregates the smart
signal outputs; the bands below describe how riskScore maps to risk levels:
| Score Range | Risk Level | Typical Indicators |
|---|---|---|
| 0-10 | Normal | Clean signals, known visitor, residential IP |
| 11-30 | Low | Minor inconsistencies, datacenter IP, or first visit |
| 31-60 | Medium | VPN detected, browser tampering, or unusual velocity |
| 61-80 | High | Multiple risk signals, proxy + tampering, high activity |
| 81-100 | Critical | Bot detected, Tor exit node, or severe anomalies |
The score computation considers 6 categories:
A human behavior discount (up to 50% reduction) is applied when mouse/keyboard interaction is confirmed.
VM detection uses 6 weighted markers:
Detection requires a GPU match plus 2+ additional markers, or 3+ markers without a GPU match.
Four privacy-focused browser configurations are detected:
| Browser | Detection Method | Threshold |
|---|---|---|
| Tor Browser | Canvas blocked + WebGL blocked + UTC timezone + limited fonts + rounded screen size | 3+ markers |
| Brave | Brave UA or navigator.brave or Client Hints "Brave" brand | 1+ marker |
| Firefox ETP (strict) | Storage partitioned + canvas resisted (Firefox UA required) | 2 markers |
| Safari ITP | Cookies blocked + IndexedDB restricted (Safari UA required) | 2 markers |
Smart Signals reach your server through the webhook payload (see Webhooks for the full shape and signature verification). The examples below read fields directly off that payload.
// `payload` is the webhook delivery body (/docs/webhooks)const score = payload.decision.riskScoreconst isVPN = payload.network.vpnconst isBot = payload.bot.result === "bot"
if (isBot) { return block("Automated access")}
if (score > 60) { return requireMFA()}
if (isVPN && score > 30) { return requireCaptcha()}
return allow()// `payload` is the webhook delivery body (/docs/webhooks)function computeFraudRisk(payload: WebhookPayload): string { let risk = "low"
if (payload.decision.suspectScore > 60) risk = "high" else if (payload.decision.suspectScore > 30) risk = "medium"
// Escalate when multiple network signals agree if (payload.network.vpn && payload.network.proxy) risk = "high" if (payload.network.tor) risk = "high" if (payload.bot.result === "bot") risk = "high"
return risk}