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 300+ 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 300 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.
El agente incluye 303 señales repartidas en 15 categorías:
| Categoría | Señales | Categoría | Señales |
|---|---|---|---|
| Navigator | 67 | Audio | 12 |
| Tamper | 56 | Privacy | 12 |
| Bot | 26 | Display | 11 |
| Canvas | 22 | Fonts | 11 |
| CSS | 18 | Network | 11 |
| Crypto | 15 | Storage | 11 |
| Persistence | 14 | Behavioral | 4 |
| Intl | 13 |
Canvas abarca WebGL y WebGPU además del renderizado 2D; Tamper es la segunda categoría más grande porque detectar un entorno modificado exige más sondeos que leer uno sin modificar.
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 con un visitante conocido, la confianza es máxima.El motor de detección de bots ejecuta múltiples detectores y combina sus salidas ponderadas en una puntuación de bot; una señal de fallo total (hard-fail) impone por sí sola un veredicto de bot. El valor público bot.score está en la escala 0..100 y el veredicto llega como bot.result. Los umbrales exactos no se publican: un umbral que se puede leer es un umbral al que se puede ajustar quien intenta esquivarlo. Los detectores que contribuyen incluyen:
Los detectores de instrumentación (Frida), de root/jailbreak y de apps clonadas existen en la plataforma, pero sus ranuras de entrada son exclusivamente nativas: el agente de navegador no las recopila, así que no contribuyen a un veredicto web. Consulte Detección de bots para ver lo que está plenamente activo en web.
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": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "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, se puede leer
mediante la Server API 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 | Descripción |
|---|---|---|
| 1 | Navegador | Inicializar el agente, crear iframe compartido |
| 2 | Navegador | Recopilar más de 300 señales (paralelo, multifase) |
| 3 | Navegador | Cifrar y comprimir la carga útil |
| 4 | Red | POST al servidor |
| 5 | Servidor | Descifrar, extraer señales, calcular ID de visitante |
| 6 | Servidor | Ejecutar detección de bots y smart signals |
| 7 | Servidor | Construir la respuesta |
| 8 | Red | Devolver la respuesta JSON |
| 9 | Navegador | Almacenar la cookie de visitante |
Ida y vuelta total: milisegundos. La recopilación de señales es lo que más pesa —los saltos de red y el trabajo del servidor son la parte menor— y varía según el dispositivo y la conexión del visitante. Nada de esto bloquea el renderizado de la página: el agente se carga de forma asíncrona y cada comprobación que puede ser lenta está acotada por su propio tiempo de espera.