uuid vs nanoid vs shortid vs randomstring
Generación de identificadores únicos en aplicaciones JavaScript
uuidnanoidshortidrandomstringPackages similaires:

Generación de identificadores únicos en aplicaciones JavaScript

nanoid, randomstring, shortid y uuid son paquetes de npm utilizados para generar cadenas únicas en aplicaciones JavaScript. Sirven para crear identificadores únicos que pueden usarse como claves en listas de React, IDs temporales antes de persistir en base de datos, tokens de sesión, códigos de verificación u otros escenarios donde se requiere unicidad y, en algunos casos, imprevisibilidad criptográfica. Cada uno tiene un enfoque distinto en cuanto a formato, seguridad, longitud y propósito principal.

Tendance de téléchargements npm

3 Ans

Classement des GitHub Stars

Détail des statistiques

Package
Téléchargements
Stars
Taille
Issues
Publication
Licence
uuid399,942,44115,34565.7 kB8il y a 22 joursMIT
nanoid360,043,58727,11814.7 kB2il y a un moisMIT
shortid1,271,9995,70921.7 kB16il y a 2 ansMIT
randomstring1,088,62452217 kB2il y a un moisMIT

Comparación técnica de generadores de identificadores únicos en JavaScript: nanoid, randomstring, shortid y uuid

Cuando desarrollamos aplicaciones modernas —ya sea en el frontend o en el backend— a menudo necesitamos generar identificadores únicos. Estos IDs pueden servir para claves de componentes React, identificadores temporales antes de guardar en base de datos, tokens de sesión, o cualquier otro caso donde necesitemos una cadena única sin colisiones predecibles. Los paquetes nanoid, randomstring, shortid y uuid ofrecen distintos enfoques para resolver este problema. Veamos cómo se comparan desde una perspectiva técnica realista.

⚠️ Estado actual: ¿Está obsoleto alguno?

Antes de comparar funcionalidades, es crucial saber si algún paquete ya no debe usarse en proyectos nuevos.

  • shortid está oficialmente marcado como obsoleto (deprecated) en su página de npm y en su repositorio de GitHub. El autor recomienda explícitamente migrar a nanoid. No debe usarse en nuevos proyectos.

Los otros tres (nanoid, randomstring, uuid) están activamente mantenidos y son seguros para uso profesional.

🔢 Formato y propósito: ¿Qué tipo de ID necesitas?

Cada paquete tiene un objetivo distinto:

  • uuid: Genera UUIDs estándar (v1, v3, v4, v5) según la especificación RFC 4122. Ideal cuando necesitas compatibilidad con sistemas que esperan UUIDs (bases de datos, APIs externas, etc.).
  • nanoid: Crea IDs alfanuméricos cortos, criptográficamente seguros y altamente eficientes. Diseñado para ser rápido, pequeño y libre de colisiones en la práctica.
  • randomstring: No está pensado principalmente para IDs únicos, sino para generar cadenas aleatorias personalizables (por ejemplo, contraseñas, códigos de verificación). Puede usarse como generador de IDs, pero no es su propósito principal.
  • shortid: Generaba IDs cortos legibles, pero su algoritmo no era criptográficamente seguro y tenía riesgos de colisión. Ya no se recomienda.

Veamos ejemplos reales de cómo se usan:

// uuid (v4 - aleatorio)
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
// nanoid
import { nanoid } from 'nanoid';
const id = nanoid(); // 'V1StGXR8_Z5jdHi6B-myT'
// randomstring
import randomstring from 'randomstring';
const id = randomstring.generate(21); // 'xK9mPq2LwRtYvN8sA4zE'
// shortid (¡NO usar en nuevos proyectos!)
import shortid from 'shortid';
const id = shortid.generate(); // 'SJj7XcJZM'

🧪 Seguridad criptográfica: ¿Es tu ID predecible?

Si tu ID se usa en contextos sensibles (tokens de autenticación, URLs privadas, etc.), debe ser impredecible. Esto requiere un generador criptográficamente seguro.

  • uuid (v4): Usa crypto.getRandomValues() en el navegador y crypto.randomBytes() en Node.js → seguro.
  • nanoid: Usa también APIs criptográficas del entorno → seguro por defecto.
  • randomstring: Por defecto no es seguro, ya que usa Math.random(). Pero puede volverse seguro si se configura con charset: 'hex' y se usa en entornos con soporte criptográfico, o si se pasa una función de aleatoriedad segura. Sin embargo, su configuración predeterminada no es apta para tokens sensibles.
  • shortid: Usaba Date.now() y contadores internos → inseguro y predecible.

Ejemplo de uso seguro en randomstring (aunque no es lo habitual):

// randomstring NO seguro por defecto
const weak = randomstring.generate(10); // ¡Evitar para tokens!

// Para hacerlo más seguro, necesitas control adicional (y aún así no es ideal)
// randomstring no expone fácilmente una API criptográfica robusta

En cambio, nanoid y uuid son seguros sin configuración adicional.

📏 Longitud y legibilidad: ¿Quieres IDs cortos?

  • uuid: Siempre genera cadenas de 36 caracteres (con guiones). Largo fijo, poco compacto.
  • nanoid: Por defecto genera IDs de 21 caracteres, pero puedes ajustar la longitud fácilmente: nanoid(10) → 'IRFa-VaY2b'.
  • randomstring: Longitud totalmente configurable: randomstring.generate({ length: 8 }).
  • shortid: Generaba IDs muy cortos (~7-10 caracteres), pero a costa de seguridad y riesgo de colisión.

Si necesitas IDs cortos y seguros, nanoid es la mejor opción entre las modernas.

🌐 Soporte para entornos: ¿Funciona en el navegador y en Node.js?

Todos los paquetes modernos funcionan en ambos entornos, pero con matices:

  • nanoid: Tiene versiones optimizadas para navegador (usa crypto.getRandomValues) y para Node.js (usa crypto.randomBytes). Además, ofrece una versión sin dependencias para bundlers.
  • uuid: Funciona en todos los entornos, incluyendo React Native y Deno.
  • randomstring: Principalmente diseñado para Node.js. Aunque puede usarse en el navegador con bundlers, su enfoque no es el frontend.
  • shortid: Funcionaba en ambos, pero ya no se mantiene.

🛠️ Personalización: ¿Necesitas control sobre los caracteres?

  • nanoid: Permite definir tu propio alfabeto:
import { customAlphabet } from 'nanoid';
const nano = customAlphabet('0123456789ABCDEF', 10);
const id = nano(); // 'A1B2C3D4E5'
  • randomstring: Ofrece muchas opciones: longitud, charset (alfanumérico, hex, ascii, etc.), incluso exclusión de caracteres ambiguos:
const id = randomstring.generate({
  length: 12,
  charset: 'alphabetic',
  capitalization: 'uppercase'
}); // 'KLMNOPQRSTUV'
  • uuid: No permite personalizar el formato del UUID v4. Si necesitas otro formato, debes procesarlo después (por ejemplo, quitar guiones).

  • shortid: Permitía cambiar el alfabeto, pero de forma limitada y sin garantías de seguridad.

🧩 Casos de uso recomendados

¿Necesitas compatibilidad con estándares empresariales o bases de datos?

→ Usa uuid. Es el estándar de facto en muchos sistemas.

¿Quieres IDs cortos, rápidos y seguros para claves de React, IDs temporales o slugs?

→ Usa nanoid. Es ligero, rápido y seguro por defecto.

¿Necesitas generar contraseñas, códigos de verificación o cadenas aleatorias no necesariamente únicas?

→ Usa randomstring, pero nunca para tokens sensibles sin asegurarte de usar una fuente criptográfica.

¿Estás manteniendo código legacy que usa shortid?

→ Migra a nanoid lo antes posible. La API es similar y la mejora en seguridad es crítica.

📊 Resumen comparativo

Característicananoidrandomstringshortiduuid
EstadoActivoActivo❌ ObsoletoActivo
Seguridad por defecto✅ Sí❌ No❌ No✅ Sí (v4)
Longitud configurable✅ Sí✅ SíParcial❌ No (36 chars)
Alfabeto personalizable✅ Sí✅ SíLimitado❌ No
Ideal para IDs únicos✅ Sí⚠️ Solo si se configura bien❌ No✅ Sí
Soporte frontend✅ Excelente⚠️ Limitado✅ (pero obsoleto)✅ Sí

💡 Conclusión práctica

  • Para la mayoría de los casos modernos en frontend (claves de listas, IDs temporales, etc.), nanoid es la mejor elección: es pequeño, rápido, seguro y flexible.
  • Si trabajas con sistemas que requieren UUIDs, no hay discusión: usa uuid.
  • Evita randomstring para generar IDs únicos críticos, a menos que sepas exactamente cómo hacerlo seguro (y en ese caso, probablemente nanoid sea más simple).
  • Nunca uses shortid en proyectos nuevos, y planifica migrar si lo tienes en producción.

La elección correcta depende del contexto, pero en 2024, para la mayoría de los desarrolladores frontend, nanoid ofrece el mejor equilibrio entre seguridad, tamaño, rendimiento y facilidad de uso.

Comment choisir: uuid vs nanoid vs shortid vs randomstring

  • uuid:

    Elige uuid si necesitas compatibilidad con el estándar RFC 4122, como cuando interactúas con bases de datos, APIs externas o sistemas empresariales que esperan UUIDs. Es la opción más segura y universal para entornos donde el formato UUID es obligatorio, aunque produce cadenas más largas que otras alternativas.

  • nanoid:

    Elige nanoid si necesitas IDs únicos, cortos, seguros y de alto rendimiento para aplicaciones modernas, especialmente en el frontend. Es ideal para claves de componentes React, IDs temporales o cualquier caso donde quieras minimizar el tamaño del bundle sin sacrificar seguridad. Su API es simple, permite personalizar el alfabeto y la longitud, y funciona perfectamente tanto en el navegador como en Node.js.

  • shortid:

    No elijas shortid para proyectos nuevos. Está oficialmente obsoleto y su algoritmo no es criptográficamente seguro, lo que puede llevar a colisiones o IDs predecibles. Si ya lo usas en código legacy, migra a nanoid, que ofrece una API similar con mejoras significativas en seguridad y mantenimiento.

  • randomstring:

    Elige randomstring si tu objetivo principal es generar cadenas aleatorias personalizables —como contraseñas, códigos de activación o placeholders— y no necesitas garantías criptográficas por defecto. Ten en cuenta que su configuración predeterminada no es segura para tokens sensibles, y no está optimizado específicamente para generar IDs únicos a gran escala.

README pour uuid

uuid CI Browser

For the creation of RFC9562 (formerly RFC4122) UUIDs

[!NOTE]

Starting with uuid@12 CommonJS is no longer supported. See implications and motivation for details.

Quickstart

1. Install

npm install uuid

2. Create a UUID

import { v4 as uuidv4 } from 'uuid';

uuidv4(); // ⇨ 'b18794e8-5d0d-417c-b361-ba38e78411b4'

For timestamp UUIDs, namespace UUIDs, and other options read on ...

API Summary

uuid.NILThe nil UUID string (all zeros)
uuid.MAXThe max UUID string (all ones)
uuid.parse()Convert UUID string to array of bytes
uuid.stringify()Convert array of bytes to UUID string
uuid.v1()Generate a version 1 (timestamp) UUID
uuid.v1ToV6()Convert a version 1 UUID to version 6
uuid.v3()Generate a version 3 (namespace w/ MD5) UUID
uuid.v4()Generate a version 4 (random) UUID
uuid.v5()Generate a version 5 (namespace w/ SHA-1) UUID
uuid.v6()Generate a version 6 (timestamp, reordered) UUID
uuid.v6ToV1()Convert a version 6 UUID to version 1
uuid.v7()Generate a version 7 (Unix Epoch time-based) UUID
uuid.v8()"Intentionally left blank"
uuid.validate()Test a string to see if it is a valid UUID
uuid.version()Detect RFC version of a UUID

API

uuid.NIL

The nil UUID string (all zeros).

Example:

import { NIL as NIL_UUID } from 'uuid';

NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000'

uuid.MAX

The max UUID string (all ones).

Example:

import { MAX as MAX_UUID } from 'uuid';

MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff'

uuid.parse(str)

Convert UUID string to array of bytes

strA valid UUID String
returnsUint8Array[16]
throwsTypeError if str is not a valid UUID

[!NOTE] Ordering of values in the byte arrays used by parse() and stringify() follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below.

Example:

import { parse as uuidParse } from 'uuid';

// Parse a UUID
uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨
// Uint8Array(16) [
//   110, 192, 189, 127,  17,
//   192,  67, 218, 151,  94,
//    42, 138, 217, 235, 174,
//    11
// ]

uuid.stringify(arr[, offset])

Convert array of bytes to UUID string

arrArray-like collection of 16 values (starting from offset) between 0-255.
[offset = 0]Number Starting index in the Array
returnsString
throwsTypeError if a valid UUID string cannot be generated

[!NOTE] Ordering of values in the byte arrays used by parse() and stringify() follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below.

Example:

import { stringify as uuidStringify } from 'uuid';

const uuidBytes = Uint8Array.of(
  0x6e,
  0xc0,
  0xbd,
  0x7f,
  0x11,
  0xc0,
  0x43,
  0xda,
  0x97,
  0x5e,
  0x2a,
  0x8a,
  0xd9,
  0xeb,
  0xae,
  0x0b
);

uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'

uuid.v1([options[, buffer[, offset]]])

Create an RFC version 1 (timestamp) UUID

[options]Object with one or more of the following properties:
[options.node = (random) ]RFC "node" field as an Array[6] of byte values (per 4.1.6)
[options.clockseq = (random)]RFC "clock sequence" as a Number between 0 - 0x3fff
[options.msecs = (current time)]RFC "timestamp" field (Number of milliseconds, unix epoch)
[options.nsecs = 0]RFC "timestamp" field (Number of nanoseconds to add to msecs, should be 0-10,000)
[options.random = (random)]Array of 16 random bytes (0-255) used to generate other fields, above
[options.rng]Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255)
[buffer]Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset
[offset = 0]Number Index to start writing UUID bytes in buffer
returnsUUID String if no buffer is specified, otherwise returns buffer
throwsError if more than 10M UUIDs/sec are requested

Example:

import { v1 as uuidv1 } from 'uuid';

uuidv1(); // ⇨ '57fd0000-c7d3-11ef-841d-514d2167fc5b'

Example using options:

import { v1 as uuidv1 } from 'uuid';

const options = {
  node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab),
  clockseq: 0x1234,
  msecs: new Date('2011-11-01').getTime(),
  nsecs: 5678,
};
uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'

uuid.v1ToV6(uuid)

Convert a UUID from version 1 to version 6

import { v1ToV6 } from 'uuid';

v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'

uuid.v3(name, namespace[, buffer[, offset]])

Create an RFC version 3 (namespace w/ MD5) UUID

API is identical to v5(), but uses "v3" instead.

[!IMPORTANT] Per the RFC, "If backward compatibility is not an issue, SHA-1 [Version 5] is preferred."

uuid.v4([options[, buffer[, offset]]])

Create an RFC version 4 (random) UUID

[options]Object with one or more of the following properties:
[options.random]Array of 16 random bytes (0-255)
[options.rng]Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255)
[buffer]Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset
[offset = 0]Number Index to start writing UUID bytes in buffer
returnsUUID String if no buffer is specified, otherwise returns buffer

Example:

import { v4 as uuidv4 } from 'uuid';

uuidv4(); // ⇨ 'b18794e8-5d0d-417c-b361-ba38e78411b4'

Example using predefined random values:

import { v4 as uuidv4 } from 'uuid';

const v4options = {
  random: Uint8Array.of(
    0x10,
    0x91,
    0x56,
    0xbe,
    0xc4,
    0xfb,
    0xc1,
    0xea,
    0x71,
    0xb4,
    0xef,
    0xe1,
    0x67,
    0x1c,
    0x58,
    0x36
  ),
};
uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'

uuid.v5(name, namespace[, buffer[, offset]])

Create an RFC version 5 (namespace w/ SHA-1) UUID

nameString | Array
namespaceString | Array[16] Namespace UUID
[buffer]Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset
[offset = 0]Number Index to start writing UUID bytes in buffer
returnsUUID String if no buffer is specified, otherwise returns buffer

[!NOTE] The RFC DNS and URL namespaces are available as v5.DNS and v5.URL.

Example with custom namespace:

import { v5 as uuidv5 } from 'uuid';

// Define a custom namespace.  Readers, create your own using something like
// https://www.uuidgenerator.net/
const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';

uuidv5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'

Example with RFC URL namespace:

import { v5 as uuidv5 } from 'uuid';

uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'

uuid.v6([options[, buffer[, offset]]])

Create an RFC version 6 (timestamp, reordered) UUID

This method takes the same arguments as uuid.v1().

import { v6 as uuidv6 } from 'uuid';

uuidv6(); // ⇨ '1efc7d35-7fd0-6000-841d-504d2167fc5b'

Example using options:

import { v6 as uuidv6 } from 'uuid';

const options = {
  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
  clockseq: 0x1234,
  msecs: new Date('2011-11-01').getTime(),
  nsecs: 5678,
};
uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'

uuid.v6ToV1(uuid)

Convert a UUID from version 6 to version 1

import { v6ToV1 } from 'uuid';

v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'

uuid.v7([options[, buffer[, offset]]])

Create an RFC version 7 (random) UUID

[options]Object with one or more of the following properties:
[options.msecs = (current time)]RFC "timestamp" field (Number of milliseconds, unix epoch)
[options.random = (random)]Array of 16 random bytes (0-255) used to generate other fields, above
[options.rng]Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255)
[options.seq = (random)]32-bit sequence Number between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value.
[buffer]Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset
[offset = 0]Number Index to start writing UUID bytes in buffer
returnsUUID String if no buffer is specified, otherwise returns buffer

Example:

import { v7 as uuidv7 } from 'uuid';

uuidv7(); // ⇨ '01941f29-7c00-73e4-a310-744d2167fc5b'

uuid.v8()

"Intentionally left blank"

[!NOTE] Version 8 (experimental) UUIDs are "for experimental or vendor-specific use cases". The RFC does not define a creation algorithm for them, which is why this package does not offer a v8() method. The validate() and version() methods do work with such UUIDs, however.

uuid.validate(str)

Test a string to see if it is a valid UUID

strString to validate
returnstrue if string is a valid UUID, false otherwise

Example:

import { validate as uuidValidate } from 'uuid';

uuidValidate('not a UUID'); // ⇨ false
uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true

Using validate and version together it is possible to do per-version validation, e.g. validate for only v4 UUIds.

import { version as uuidVersion } from 'uuid';
import { validate as uuidValidate } from 'uuid';

function uuidValidateV4(uuid) {
  return uuidValidate(uuid) && uuidVersion(uuid) === 4;
}

const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210';
const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836';

uuidValidateV4(v4Uuid); // ⇨ true
uuidValidateV4(v1Uuid); // ⇨ false

uuid.version(str)

Detect RFC version of a UUID

strA valid UUID String
returnsNumber The RFC version of the UUID
throwsTypeError if str is not a valid UUID

Example:

import { version as uuidVersion } from 'uuid';

uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // ⇨ 1
uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4

[!NOTE] This method returns 0 for the NIL UUID, and 15 for the MAX UUID.

Command Line

UUIDs can be generated from the command line using uuid.

$ npx uuid
ddeb27fb-d9a0-4624-be4d-4615062daed4

The default is to generate version 4 UUIDS, however the other versions are supported. Type uuid --help for details:

$ npx uuid --help

Usage:
  uuid
  uuid v1
  uuid v3 <name> <namespace uuid>
  uuid v4
  uuid v5 <name> <namespace uuid>
  uuid v7
  uuid --help

Note: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs
defined by RFC9562

options Handling for Timestamp UUIDs

Prior to uuid@11, it was possible for options state to interfere with the internal state used to ensure uniqueness of timestamp-based UUIDs (the v1(), v6(), and v7() methods). Starting with uuid@11, this issue has been addressed by using the presence of the options argument as a flag to select between two possible behaviors:

  • Without options: Internal state is utilized to improve UUID uniqueness.
  • With options: Internal state is NOT used and, instead, appropriate defaults are applied as needed.

Support

Browsers: uuid builds are tested against the latest version of desktop Chrome, Safari, Firefox, and Edge. Mobile versions of these same browsers are expected to work but aren't currently tested.

Node: uuid builds are tested against node (LTS releases), plus one prior. E.g. At the time of this writing node@20 is the "maintenance" release and node@24 is the "current" release, so uuid supports node@20-node@24.

Typescript: TS versions released within the past two years are supported. source

Known issues

"getRandomValues() not supported"

This error occurs in environments where the standard crypto.getRandomValues() API is not supported. This issue can be resolved by adding an appropriate polyfill:

React Native / Expo

  1. Install react-native-get-random-values
  2. Import it before uuid. Since uuid might also appear as a transitive dependency of some other imports it's safest to just import react-native-get-random-values as the very first thing in your entry point:
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';

Generated from README_js.md by runmd