
Demostración educativa de evercookie que muestra cómo las técnicas de almacenamiento del navegador y de caché HTTP pueden reidentificar de forma persistente a un visitante.
Una demostración educativa de cómo los sitios web te identifican de forma persistente — y por qué "borrar tus cookies" ya no es suficiente.
ubercookie planta un único id aleatorio en 12 vectores de almacenamiento del navegador a la vez. Cada vez que visitas, los lee todos, llega a un consenso y reescribe el id en todos ellos. Borra cualquiera de los almacenes —o incluso todas tus cookies— y los supervivientes lo regeneran silenciosamente. El sitio te muestra, con un lenguaje claro, exactamente dónde se esconde tu id y con qué frecuencia ha reconocido tu navegador.
Es la misma idea del clásico evercookie de Samy Kamkar, construido aquí como una herramienta didáctica abierta y transparente centrada en la regeneración del almacenamiento y la persistencia de las supercookies.
[!IMPORTANT] Este proyecto rastrea al visitante a propósito, para concienciar. Es solo de primera parte, almacena únicamente un id aleatorio, contadores de visitas, marcas de tiempo de primera/última visita y etiquetas de la fuente de recuperación, no comparte nada con terceros e incluye un botón "Olvídame" real. No lo reutilices para rastrear a personas sin su conocimiento o consentimiento: eso es lo contrario del propósito. Consulta Ética.
| Vector | Tipo | ¿Necesita JS? | ¿Borrable desde JS? | Qué enseña |
|---|---|---|---|---|
document.cookie | cliente | sí | sí | El rastreador base |
localStorage | cliente | sí | sí | Sobrevive al borrado de cookies |
sessionStorage | cliente | sí | sí | Redundancia por pestaña |
IndexedDB | cliente | sí | sí | Una base de datos completa que la gente olvida borrar |
Cache API (caches) | cliente | sí | sí | Almacén programable, separado de los anteriores |
window.name | cliente | sí | sí | Persiste entre navegaciones |
| OPFS (Origin Private File System) | cliente | sí | sí | Un sistema de archivos de espacio aislado que las limpiezas manuales pasan por alto |
| Service Worker + Cache | cliente | sí | sí | Script en segundo plano que vuelve a servir el id, incluso sin conexión |
Cookie de servidor (HttpOnly) | servidor | no | vía servidor | Invisible para JS, se envía en cada petición |
| ETag supercookie | servidor | no | solo limpieza de caché | El id se devuelve en If-None-Match |
| Last-Modified supercookie | servidor | no | solo limpieza de caché | El id codificado en la fecha del recurso cacheado |
| Caché HTTP (script con id incrustado) | servidor | no | solo limpieza de caché | El id incrustado en un archivo cacheado immutable |
Además de estos, la página solicita al navegador almacenamiento persistente (navigator.storage.persist()), que exime a las copias de IndexedDB / Cache / Service Worker / OPFS del desalojo automático, lo que hace que sea aún más difícil deshacerse de ellas.
Los tres vectores basados en caché son el remate de la persistencia: viven en la caché HTTP del navegador, por lo que JavaScript (incluido nuestro propio Olvídame) no puede eliminarlos: solo borrar la caché del navegador lo consigue. Así es como el id regresa de entre los muertos.
Una guía completa de los vectores de almacenamiento implementados, además de la idea de la supercookie HSTS que todavía encaja en este proyecto, está en docs/techniques.md.
ubercookie/
├── backend/ FastAPI — server-side vectors + the observation log (SQLite)
│ └── app/
│ ├── main.py endpoints: /api/visit, /api/whoami, /api/etag-id,
│ │ /api/lastmod-id, /api/cache-id.js, /api/clear-cookie,
│ │ /api/forget
│ ├── store.py "we've seen this browser N times" memory
│ └── ids.py mint/validate the 32-hex tracking id
└── frontend/ Vanilla JS + Vite — the dashboard and the client vectors
└── src/ubercookie/
├── index.js orchestrator: read-all → consensus → respawn → report
└── vectors/ one self-contained module per storage vector
Cómo funciona una visita (frontend/src/ubercookie/index.js):
HttpOnly.Requiere Python ≥ 3.11 (con uv) y Node ≥ 18.
make install # backend deps (uv) + frontend deps (npm)
# then, in two terminals:
make backend # FastAPI on http://localhost:8000
make frontend # Vite on http://localhost:5173 (proxies /api → :8000)
Abre http://localhost:5173 y observa cómo te rastrean. Abre DevTools, borra algunos almacenes, pulsa Volver a escanear y observa cómo reaparecen.
Un solo comando para ambos servidores a la vez:
./scripts/dev.sh
make build # → frontend/dist
cd backend && uv run uvicorn app.main:app --port 8000
# open http://localhost:8000
Servir ambos desde un único origen es la configuración más fiel, porque los vectores de caché/ETag dependen del almacenamiento en caché HTTP real del mismo origen.
make test # backend pytest (server-side vector logic + observation log)
make build # frontend production build
Las pruebas del backend ejercitan los vectores del lado del servidor y el registro de observación. El comportamiento del navegador aún requiere un navegador real para verificarse, porque varios vectores dependen del almacenamiento del origen, los Service Workers y el almacenamiento en caché HTTP.
Es una herramienta defensiva / de concienciación. Pautas integradas en el diseño:
Por favor, mantén cualquier fork con el mismo espíritu: úsalo para enseñar a la gente cómo funciona el rastreo para que pueda defenderse, no para rastrearla de forma encubierta.
MIT — consulta LICENSE.