TRACIO es un sistema de identificación cliente-servidor. El cliente recopila señales del navegador y las envía al servidor, que calcula un identificador de visitante estable, ejecuta algoritmos de detección y devuelve resultados enriquecidos. Esta sección explica cada etapa del pipeline.
Browser TRACIO Cloud | | |-- Tracio.init({ publicKey }) ---------> | (init, no network) | | |-- tracio.getResult() ----------------> | | 1. Collect 130+ browser signals | | 2. Encrypt (XOR + deflate + B64) | | 3. POST to ingress endpoint | | | | |-- Decrypt & extract signals | |-- Compute visitor ID (MurmurHash3-128) | |-- Run bot detection (weighted scoring) | |-- Run smart signals (server-side enrichment) | |-- Run IP intelligence (VPN/proxy/Tor) | |-- Store visit event | | |<-- JSON response ------------------- | | visitorId, confidence, | | bot detection, smart signals | | | |-- Store visitor cookie (_vid_t) -----> | (365-day persistence)Cuando se llama a tracio.getResult(), el cliente recopila más de 130 señales distintas del navegador organizadas en niveles. La recopilación usa un pipeline multifase con Web Workers e iframes compartidos para mejorar el rendimiento.
| Categoría | Nº de señales | Ejemplos |
|---|---|---|
| Canvas y WebGL | 9 | Huella de canvas, renderizador de WebGL, parámetros de WebGL, WebGPU |
| Audio | 3 | Huella de AudioContext, latencia base, temporización de DRM |
| Fuentes y renderizado | 10 | Detección de fuentes, preferencias de fuentes, MathML, renderizado de emojis |
| Navigator y plataforma | 25 | User-Agent, idiomas, pantalla, concurrencia de hardware, zona horaria |
| Almacenamiento y cookies | 10 | localStorage, sessionStorage, cookies, cuota de almacenamiento |
| CSS y media queries | 10 | Esquema de color, HDR, movimiento reducido, colores forzados |
| Red y WebRTC | 3 | Sonda TURN, RTT de la conexión, versión de la app |
| Detección de bots | 15 | Bandera webdriver, frameworks de automatización, longitud de eval |
| Detección de manipulación | 8 | Introspección de getters de propiedades, cadenas de prototipos, integridad de funciones nativas |
| Extensiones personalizadas | 14 | Huella matemática, detección de arquitectura, características de WASM |
El pipeline de recopilación se ejecuta en cuatro etapas para minimizar el bloqueo del hilo principal:
Etapa 1 (inmediata): señales de alta prioridad que se recopilan rápido (propiedades del navigator, pantalla, zona horaria). La sonda TURN también arranca aquí, ya que se ejecuta de forma concurrente.
Etapa 2 (idle callback): señales síncronas que se benefician de un periodo de inactividad (media queries de CSS, sondas de almacenamiento, pruebas de cookies).
Etapa 3 (asíncrona): señales que requieren APIs asíncronas o renderizado (canvas, WebGL, huella de audio, detección de fuentes, renderizado de emojis).
Web Worker: recopilación aislada de señales en un hilo dedicado (detección de características de WASM, doNotTrack).
Se crea un iframe oculto compartido una sola vez y lo reutilizan varios recopiladores (emojis, MathML, colores del sistema, fuentes, frame de pantalla) para evitar la sobrecarga de crear iframes separados por señal.
Cada señal sigue una estructura consistente:
interface Signal<T> { s: number // Status code v: T // Value (when successful)}Códigos de estado:
| Código | Significado |
|---|---|
0 | Éxito |
-1 | No disponible (propiedad indefinida) |
-2 | La comprobación secundaria falló |
-3 | Comportamiento inesperado |
-4 | Tiempo de espera agotado |
-5 | Deshabilitado |
-6 | Bloqueado por CSP |
-7 | Error de seguridad |
Las señales recopiladas se serializan a JSON y luego se cifran y comprimen antes de la transmisión:
Serialización a JSON: todos los valores de las señales se empaquetan en un objeto JSON indexado por señal, más campos de metadatos (c para la clave de API, t para la etiqueta, lid para el ID vinculado).
Compresión: si la carga útil supera los 1024 bytes, se comprime con CompressionStream("deflate-raw").
Cifrado XOR: la carga útil se envuelve en un sobre de cifrado:
Codificación Base64: la carga útil cifrada se codifica en Base64url y se envía como cuerpo del POST.
La solicitud se envía al endpoint de ingreso con parámetros de consulta para la versión del cliente y la clave de API. Se incluyen las credenciales de CORS para enviar las cookies de origen.
El servidor recibe la carga útil cifrada y la procesa a través de varios subsistemas:
El servidor decodifica el sobre XOR, descomprime si es necesario y analiza los datos de señales en JSON. El código de estado y el valor de cada señal se extraen y validan.
El ID de visitante se calcula mediante un enfoque de hashing escalonado (V3):
Tier 1 (Frozen): 20 base62 characters - Stable hardware signals that rarely change - Canvas, WebGL renderer, audio fingerprint, fonts - Provides long-term visitor identity
Tier 2 (Semi-stable): 10 base62 characters - Signals that change with browser updates - User-Agent data, Client Hints, plugins - Extensible without breaking Tier 1
Tier 3 (Volatile): 10 base62 characters - Signals that change frequently - Screen resolution, timezone, language - Used for confidence scoring, not identityCada nivel extrae sus señales designadas, construye una cadena canónica y la somete a hash con MurmurHash3-x64-128. Los tres hashes de nivel se concatenan y se codifican en base62 para producir el ID de visitante final.
La puntuación de confianza (de 0.0 a 1.0) indica cuán seguro está el sistema de que este visitante ha sido identificado correctamente:
_vid_t coincide, la confianza es máxima.El motor de detección de bots ejecuta múltiples detectores cuyas salidas ponderadas se combinan en una puntuación de bot (umbrales: bot ≥ 0.70, suspicious ≥ 0.30; una señal de fallo total fuerza un veredicto de bot). Los detectores que contribuyen incluyen:
Las señales de enriquecimiento del lado del servidor se calculan a partir de los datos de señales en bruto y de la inteligencia de IP. Incluyen la detección de VPN/proxy/Tor, la geolocalización de IP, el análisis de manipulación del navegador y la puntuación de sospecha.
El subsistema de IP Intelligence proporciona:
El servidor devuelve una respuesta JSON que contiene:
{ "visitorId": "X7fh2Hg9LkMn3pQr", "bot": { "detected": false, "confidence": 2, "reasons": [] }}Este es el resultado al que se resuelve tracio.getResult() en el navegador. El
evento completo y enriquecido —incluidos el bot_result canónico
(human / bot / uncertain), la geolocalización y las smart signals— se
entrega del lado del servidor a través de webhooks y se muestra en el
panel.
El cliente almacena un token de visitante tanto en una cookie de origen (caducidad de 365 días, SameSite=Lax) como en localStorage para lograr persistencia entre sesiones.
| Paso | Ubicación | Duración | Descripción |
|---|---|---|---|
| 1 | Navegador | ~5ms | Inicializar el agente, crear iframe compartido |
| 2 | Navegador | ~50-150ms | Recopilar más de 130 señales (paralelo, multifase) |
| 3 | Navegador | ~5ms | Cifrar y comprimir la carga útil |
| 4 | Red | ~10-50ms | POST al servidor |
| 5 | Servidor | ~5-20ms | Descifrar, extraer señales, calcular ID de visitante |
| 6 | Servidor | ~5-15ms | Ejecutar detección de bots y smart signals |
| 7 | Servidor | ~5ms | Construir la respuesta |
| 8 | Red | ~10-50ms | Devolver la respuesta JSON |
| 9 | Navegador | ~1ms | Almacenar la cookie de visitante |
Ida y vuelta total: normalmente entre 80 y 300ms según las condiciones de la red y las capacidades del navegador.