This page covers common issues encountered during TRACIO integration and their solutions.
Browser console shows:
Access to XMLHttpRequest at 'https://app.tracio.ai/' from origin'https://your-app.com' has been blocked by CORS policy: No'Access-Control-Allow-Origin' header is present on the requested resource.Your server or reverse proxy is not setting the required CORS headers. TRACIO sends requests with credentials: include, which requires specific CORS configuration.
Add the following headers to your Nginx configuration:
location / { proxy_pass http://127.0.0.1:8080;
# CORS headers — must include credentials support add_header Access-Control-Allow-Origin $http_origin always; add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
# Handle preflight if ($request_method = OPTIONS) { return 204; }}Important notes:
Access-Control-Allow-Origin must echo back the requesting origin (not *), because credentials: include requires a specific originAccess-Control-Allow-Credentials must be trueOPTIONS preflight response must include all CORS headersIf your server is behind Cloudflare, ensure:
Always Online feature is disabled for the TRACIO endpoint (it can cache error responses)Confidence scores are consistently below 0.90 for returning visitors.
1. Cookie not persisting
The _tcid cookie may not be setting correctly. Check in the browser:
// In browser consoledocument.cookie.split(";").filter((c) => c.includes("_tcid"))If the cookie is missing, see the Cookie Not Persisting section below.
2. Recently deployed server
After a fresh deployment, the visitor database is empty. All visitors appear as "new" with a confidence of 0.90. After 24-48 hours, returning visitors will be recognized with higher confidence.
3. Cross-subdomain deployment
If your app runs on app.example.com but TRACIO is deployed on tracio.example.com, ensure the cookie domain is set to .example.com (note the leading dot). This is handled automatically by TRACIO's domain probing, but verify:
# Check the Set-Cookie header in the responsecurl -v https://app.tracio.ai/health 2>&1 | grep Set-Cookie4. Incognito/private browsing
In incognito mode, cookies and localStorage are cleared when the session ends. TRACIO falls back to signal-only matching, which has lower confidence (typically 0.85-0.95).
5. Browsers with aggressive anti-fingerprinting
Brave, Firefox (strict mode), and Safari (ITP) modify or block some browser signals. This reduces the signal set available for matching. TRACIO detects these browsers and adjusts confidence accordingly.
Query the Server API to see the full identification details:
curl https://app.tracio.ai/api/v1/subscriptions/:id/events/REQUEST_ID \ -H "Authorization: Bearer <clerk-session-jwt>"Check:
confidence: The computed model confidence (0.0–1.0)incognito: Is private browsing detected?bot_result: human, bot, or uncertaintimestamp: When the event was capturedLegitimate human visitors are flagged as bots.
1. Browser extensions modifying navigator properties
Some privacy extensions modify navigator.userAgent, navigator.platform, or other properties. This can trigger the tampering detector but should not trigger bot detection alone.
Check the bot_type field to identify which detector fired:
| bot_type | Common False Positive Cause | Solution |
|---|---|---|
webdriver | Browser testing tool left navigator.webdriver = true | User should disable testing mode |
headless | VNC/remote desktop with software GPU rendering | Check if SwiftShader/llvmpipe is the GPU renderer |
unknown | Eval length anomaly from browser extension | Review the extension |
rateBot | Automated page refreshing or aggressive polling | Reduce request frequency |
2. Corporate environments with software rendering
Citrix, VDI, and terminal server environments often use software GPU rendering (SwiftShader, llvmpipe), which is a headless marker. If your users operate in these environments:
// Server-side: check if the bot detection is a VDI false positive// `data` is the flat event from the Server API (/docs/api-reference)const { data: event } = await fetchEvent(requestId)
if (event.bot_result === "bot" && event.bot_type === "headless") { // Software-GPU (SwiftShader/llvmpipe) VDI users can trip the headless // detector — consider applying a softer policy for these.}3. Automated testing in production
If your QA team runs Selenium/Playwright tests against production, those will correctly be detected as bots. Use a separate API key for test traffic or allowlist test IPs.
The _tcid cookie disappears between visits, causing every visit to appear as a "new" visitor.
1. Missing Secure flag on HTTP
The _tcid cookie uses the Secure flag and will only be set over HTTPS. Ensure your TRACIO endpoint uses HTTPS.
2. SameSite attribute conflicts
TRACIO sets SameSite=Lax on the cookie. If your site loads TRACIO from a different origin (cross-site), the cookie will be blocked. Solution: use a custom subdomain proxy.
Good: app.example.com → tracio.example.com (same-site, cookie works)Bad: app.example.com → api.other-domain.com (cross-site, cookie blocked)3. Cookie domain mismatch
If the cookie domain does not match your application domain, the browser will not send it. Check the cookie domain in browser DevTools → Application → Cookies.
4. Safari ITP
Safari's Intelligent Tracking Prevention (ITP) limits cookie lifetime for some classifications. TRACIO sets cookies server-side via Set-Cookie header (not JavaScript), which is more resilient to ITP. Verify the cookie is set as HttpOnly.
5. Browser clearing cookies
Some browsers (Brave, Firefox Focus) clear cookies on session end. Users with aggressive privacy settings will always appear as new visitors.
tracio.getResult() takes more than 500ms to return.
1. Slow network to server
Check network latency:
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" https://app.tracio.ai/healthTarget: Total under 100ms from your users' typical location.
2. Server resource contention
Check server metrics:
# CPU usagedocker stats tracio-ingress
# Redis latencyredis-cli --latency
# PostgreSQL connectionspsql -c "SELECT count(*) FROM pg_stat_activity;"3. Signal collection taking too long
Some signals have timeouts. On slow devices, collection can take 200ms+. The signals most likely to cause delays:
| Signal | Timeout | Cause |
|---|---|---|
| Audio fingerprint (s21) | 500ms / 5000ms | AudioContext suspended (iOS) |
| TURN probe (s94) | 300ms | TURN server unreachable or slow |
| Font detection (s20) | None | Many fonts = slow DOM measurement |
| DRM timing (s95) | 1000ms | Widevine license request |
4. DNS resolution
If using a custom domain, ensure DNS resolution is fast. Consider using a CDN or setting a low TTL.
Some signals return status -1 (not available) or other error codes.
| Signal | Error | Cause | Impact |
|---|---|---|---|
| s17 (canvas) | -6 | CSP blocks inline canvas rendering | Reduces identification accuracy by ~5% |
| s21 (audio) | -4 | AudioContext timeout on iOS | Reduces accuracy by ~3% |
| s70 (WebGPU) | -1 | Browser does not support WebGPU | Normal, expected on most browsers |
| s94 (TURN) | -4 | TURN server unreachable | Reduces VPN detection accuracy |
| s58 (ClientHints) | -7 | Not available in Firefox/Safari | Normal, Chrome/Edge only |
Signal errors are expected and handled gracefully. The system adjusts confidence scoring based on available signals. No action is required unless critical signals (canvas, WebGL, audio) consistently fail.
Server logs show Redis connection errors. Velocity tracking and visitor caching fail.
# Check Redis connectivityredis-cli -h redis-host -p 6379 ping
# Check Redis memory usageredis-cli info memory
# Check max connectionsredis-cli config get maxclientsEnsure the TRACIO_REDIS_URL environment variable is correct and the Redis instance is reachable from the TRACIO server container.
If you encounter an issue not covered here:
docker compose logs tracio-ingressTRACIO_LOG_LEVEL=debughttps://app.tracio.ai/demo