TRACIO matches FingerprintJS Pro v4's browser signal collection while exposing
its own SDK (@tracio/sdk) and Server API. This guide covers the migration
process, signal parity details, and the differences in the SDK and response
formats you will need to update.
| Aspect | FingerprintJS Pro | TRACIO | Compatible |
|---|---|---|---|
| Signal collection | XOR + deflate + Base64 | Equivalent | Yes |
| Signal count | ~133 | 130+ (FingerprintJS-matching + proprietary) | Yes |
| Signal format | { s: status, v: value } | Equivalent | Yes |
| Client SDK | @fingerprintjs/fingerprintjs-pro | @tracio/sdk (Tracio.init) | Code change |
| Client result shape | { visitorId, confidence, ... } | { visitorId, bot: { detected, ... } } | Code change |
| Server API | products.{ identification, botd, ... } | Flat snake_case event in { ok, data } | Code change |
| Webhooks | FingerprintJS webhook format | Flat camelCase payload, X-Tracio-Signature | Code change |
| Cookie mechanism | _iidt / _vid_t (365 days) | _tcid (365 days, AES-GCM) | Different |
Every signal collected by FingerprintJS Pro v4 is matched by TRACIO. Verified via automated Playwright comparison tests running side-by-side against the production FingerprintJS Pro endpoint.
| Signal Range | Count | Match Rate |
|---|---|---|
| s1 - s30 | 30 | 100% |
| s31 - s60 | 30 | 100% |
| s61 - s100 | 40 | 100% |
| s101 - s140 | 20 | 100% |
| s141 - s212 | 12 | 100% |
| Custom s300 - s313 | 14 | N/A (our extensions) |
Create your TRACIO account and get API keys. See Cloud Deployment for complete instructions.
# Quick deploy with Docker Composegit clone https://github.com/anthropic/fp.gitcd fpcp .env.example .env# Edit .env with your configurationdocker compose up -dVerify the server is running:
curl https://app.tracio.ai/health# { "status": "ok" }Before switching your production traffic, test with TRACIO's client SDK. Note that TRACIO uses its own SDK and API — it is not a drop-in protocol replacement for the FingerprintJS client.
import { Tracio } from "@tracio/sdk"
const tracio = Tracio.init({ publicKey: "5ca175fc...",})
const result = await tracio.getResult()console.log(result)Compare the detected device against your existing FingerprintJS Pro integration to verify the migration.
For critical deployments, run both systems simultaneously and compare results:
// Temporary: run both systems and compareconst fpjsResult = await fpjsAgent.get() // FingerprintJS Pro agentconst tracioResult = await tracio.getResult() // TRACIO instance
// Compare visitor IDs (they will differ — different servers)// But bot detection should be equivalent for the same deviceconsole.log("FPJS visitorId:", fpjsResult.visitorId)console.log("TRACIO visitorId:", tracioResult.visitorId)console.log("FPJS bot:", fpjsResult.bot)console.log("TRACIO bot:", tracioResult.bot)Note that visitor IDs will be different between systems since they are computed from different server-side databases. The key compatibility metric is that both systems identify the same physical device consistently.
TRACIO ships its own client SDK (@tracio/sdk) and does not reuse the
FingerprintJS client protocol, so this is a code change rather than a DNS swap.
Remove the FingerprintJS client and initialize TRACIO with your public key:
// Before (FingerprintJS Pro)import * as FingerprintJS from "@fingerprintjs/fingerprintjs-pro"const fpAgent = await FingerprintJS.load({ apiKey: "fpjs-public-key" })const fpResult = await fpAgent.get()
// After (TRACIO)import { Tracio } from "@tracio/sdk"const tracio = Tracio.init({ publicKey: "5ca175fc..." })const result = await tracio.getResult()If your backend queries the FingerprintJS Pro Server API, switch to the TRACIO Server API. The endpoint, auth model, and response shape are different:
// Before (FingerprintJS Pro)const response = await fetch(`https://eu.api.fpjs.io/events/${requestId}`, { headers: { "Auth-API-Key": "fpjs-api-key" },})
// After (TRACIO) — workspace-scoped, authenticated with the dashboard sessionconst response = await fetch( `https://app.tracio.ai/api/v1/subscriptions/${workspaceId}/events/${requestId}`, { headers: { Authorization: "Bearer <clerk-session-jwt>" } },)The TRACIO response is a flat, snake_case event wrapped in an { ok, data }
envelope (see the Server API Reference) — it does not
use the FingerprintJS products structure.
If you use webhooks, register them in the TRACIO dashboard. The
webhook payload is a flat, camelCase document signed with an
X-Tracio-Signature header — it differs from the FingerprintJS webhook format,
so update your handler accordingly.
Once TRACIO is verified in production:
TRACIO and FingerprintJS use different response shapes — this is the main thing to account for when porting code.
The TRACIO client SDK resolves to a compact result:
{ "visitorId": "X7fh2Hg9LkMn3pQr", "bot": { "detected": false, "confidence": 2, "reasons": [] }}The TRACIO Server API returns a flat, snake_case event in an { ok, data }
envelope — not the FingerprintJS products structure:
{ "ok": true, "data": { "request_id": "1710432000_abc123def", "visitor_id": "X7fh2Hg9LkMn3pQr", "confidence": 0.95, "bot_result": "human", "bot_type": "", "ip": "94.142.239.124", "ip_country": "CZ", "ip_city": "Prague", "decision": "real", "risk_score": 4 }}See the Server API Reference for the full field list.
TRACIO is not a drop-in protocol replacement for FingerprintJS. Beyond the different SDK and response shapes above, note:
Visitor IDs will not be the same between FingerprintJS Pro and TRACIO. The visitor ID is a hash of browser signals, and each system uses its own hashing parameters and database. After migration, every visitor will appear as a "new" visitor in TRACIO's database.
Mitigation: Use the linkedId field to map TRACIO visitor IDs to your existing user accounts or sessions. After a transition period, TRACIO's visitor database will build up naturally.
| System | Cookie Name | Encryption |
|---|---|---|
| FingerprintJS Pro | _iidt (via proxy) or _vid_t (client-side) | None (plain token) |
| TRACIO | _tcid | AES-256-GCM encrypted |
The cookie name difference means existing FingerprintJS Pro cookies will not carry over. Visitors will receive new cookies from TRACIO.
TRACIO collects additional proprietary signals that are not present in FingerprintJS Pro. These provide additional detection capabilities but do not affect compatibility with existing integrations.
FingerprintJS Pro provides sealed_result in the response (an encrypted blob for server-side verification). TRACIO does not currently support sealed results. Use the Server API for verification instead.
If you see CORS errors after switching DNS, ensure your Nginx configuration includes:
add_header Access-Control-Allow-Origin $http_origin always;add_header Access-Control-Allow-Credentials true always;After migration, confidence scores may be slightly lower for the first 24-48 hours as TRACIO builds its visitor database. This is expected and resolves as visitors return and establish cookie-based identities.
Verify that all required external services are configured:
Confirm you have replaced the FingerprintJS client with @tracio/sdk and that
Tracio.init() is called with a valid public key for the
correct workspace.