Las aplicaciones web necesitan almacenar datos en el lado del cliente: preferencias del usuario, tokens de autenticación, datos cacheados, contenidos del carrito de compras, borradores de formularios. Los navegadores ofrecen varios mecanismos de almacenamiento, cada uno con características distintas. Elegir el incorrecto puede generar cuellos de botella en el rendimiento, vulnerabilidades de seguridad o pérdida de datos.

Comparación Rápida

Opciones de Almacenamiento de un Vistazo
Característica     localStorage    sessionStorage   Cookies          IndexedDB
──────────────────────────────────────────────────────────────────────────────
Capacidad        5-10 MB         5-10 MB          ~4 KB/cookie     100MB+
Persistencia     Permanente      Vida de la pestaña   Configurable     Permanente
Enviado al servidor No              No               Sí (cada req)    No
Acceso           JS Síncrono     JS Síncrono      JS + HTTP        JS Asíncrono
Formato de datos  Cadena          Cadena           Cadena           Cualquiera (objetos)
Caso de uso       Preferencias    Estado temporal  Tokens de autenticación Datos grandes

localStorage

Almacena pares clave-valor sin fecha de expiración. Los datos persisten hasta que son explícitamente borrados por el usuario o por tu código.

API de localStorage
// Almacenar datos (solo cadenas)
localStorage.setItem('tema', 'oscuro');
localStorage.setItem('usuario', JSON.stringify({ nombre: 'Ana', id: 123 }));

// Recuperar datos
const tema = localStorage.getItem('tema'); // "oscuro"
const usuario = JSON.parse(localStorage.getItem('usuario'));

// Eliminar un elemento específico
localStorage.removeItem('tema');

// Borrar todos los datos
localStorage.clear();

// Comprobar uso del almacenamiento
const used = new Blob(Object.values(localStorage)).size;
console.log(`${(used / 1024).toFixed(1)} KB utilizados`);

Ideal para: Preferencias de tema, elección de idioma, estado de la interfaz de usuario (barra lateral abierta/cerrada), configuraciones no sensibles.

⚠️ Nunca almacenes: Tokens de autenticación, contraseñas, ni ningún dato sensible. localStorage es accesible para todo el JavaScript en la página, incluidos los scripts inyectados por XSS.

sessionStorage

API idéntica a localStorage, pero los datos están limitados a la pestaña actual del navegador y se borran cuando la pestaña se cierra.

Caso de Uso de sessionStorage
// Almacenar datos de formulario (recuperables en navegación accidental)
const datosFormulario = { nombre: inputNombre.value, email: inputEmail.value };
sessionStorage.setItem('borradorFormulario', JSON.stringify(datosFormulario));

// Restaurar al cargar la página
window.addEventListener('load', () => {
  const borrador = sessionStorage.getItem('borradorFormulario');
  if (borrador) {
    const { nombre, email } = JSON.parse(borrador);
    inputNombre.value = nombre;
    inputEmail.value = email;
  }
});

Ideal para: Datos de formularios de varios pasos, estado temporal de asistentes, datos por pestaña que no deben filtrarse entre pestañas.

Cookies

El mecanismo de almacenamiento más antiguo. A diferencia de localStorage, las cookies se envían al servidor con cada solicitud HTTP, lo que las hace ideales para la autenticación pero terribles para el almacenamiento de grandes cantidades de datos.

Configuración Segura de Cookies
// Establecer una cookie (lado del servidor — Express.js)
res.cookie('session_id', 'abc123', {
  httpOnly: true,   // JavaScript no puede acceder a esta cookie (protección XSS)
  secure: true,     // Solo se envía a través de HTTPS
  sameSite: 'Lax',  // Protección CSRF
  maxAge: 86400000, // Expira en 24 horas (milisegundos)
  path: '/',
});

// Establecer una cookie (JavaScript del lado del cliente)
document.cookie = "tema=oscuro; path=/; max-age=31536000; SameSite=Lax";

// Leer cookies (lado del cliente) — API incómoda
const tema = document.cookie
  .split('; ')
  .find(row => row.startsWith('tema='))
  ?.split('=')[1]; // "oscuro"

Ideal para: IDs de sesión, tokens de autenticación (con httpOnly + secure + sameSite).

⚠️ Indicadores de cookie importantes:

  • httpOnly — No puede ser leída por JavaScript (previene el robo de tokens XSS)
  • secure — Solo se envía a través de HTTPS
  • sameSite=Lax|Strict — Protección CSRF

IndexedDB

Una base de datos completa en el lado del cliente. Almacena datos estructurados (objetos, archivos, blobs) con índices para consultas. API asíncrona. Capacidad de cientos de megabytes.

Ejemplo de IndexedDB
// Abrir base de datos
const request = indexedDB.open('MiApp', 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore('productos', { keyPath: 'id' });
  store.createIndex('categoria', 'categoria', { unique: false });
};

request.onsuccess = (event) => {
  const db = event.target.result;

  // Añadir datos
  const tx = db.transaction('productos', 'readwrite');
  tx.objectStore('productos').add({
    id: 1,
    nombre: 'Herramienta',
    categoria: 'utensilios',
    precio: 29.99,
  });

  // Leer datos
  const getTx = db.transaction('productos', 'readonly');
  const getReq = getTx.objectStore('productos').get(1);
  getReq.onsuccess = () => console.log(getReq.result);
};

Ideal para: Aplicaciones con capacidad offline, caché de grandes conjuntos de datos, almacenamiento de archivos/blobs, Progressive Web Apps (PWAs).

Guía de Decisión

  • ¿Preferencias de tema/idioma? → localStorage
  • ¿Datos de borrador de formulario? → sessionStorage
  • ¿Sesión de autenticación? → Cookie HttpOnly Segura
  • ¿Carrito de compras? → localStorage (invitado) o lado del servidor (iniciado sesión)
  • ¿Caché de datos offline? → IndexedDB
  • ¿Almacenamiento de archivos grandes? → IndexedDB
  • ¿Datos necesarios por el servidor? → Cookie

Prueba Nuestras Herramientas Gratuitas para Desarrolladores

Codifica y decodifica datos para el almacenamiento del lado del cliente.