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.
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.
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.
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'
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.
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.
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.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.
→ Usa uuid. Es el estándar de facto en muchos sistemas.
→ Usa nanoid. Es ligero, rápido y seguro por defecto.
→ Usa randomstring, pero nunca para tokens sensibles sin asegurarte de usar una fuente criptográfica.
shortid?→ Migra a nanoid lo antes posible. La API es similar y la mejora en seguridad es crítica.
| Característica | nanoid | randomstring | shortid | uuid |
|---|---|---|---|---|
| Estado | Activo | Activo | ❌ Obsoleto | Activo |
| 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í |
nanoid es la mejor elección: es pequeño, rápido, seguro y flexible.uuid.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).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.
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.
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.
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.
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.
For the creation of RFC9562 (formerly RFC4122) UUIDs
crypto API for random valuesuuid command line utility[!NOTE]
Starting with
uuid@12CommonJS is no longer supported. See implications and motivation for details.
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 ...
uuid.NIL | The nil UUID string (all zeros) |
uuid.MAX | The 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 |
The nil UUID string (all zeros).
Example:
import { NIL as NIL_UUID } from 'uuid';
NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000'
The max UUID string (all ones).
Example:
import { MAX as MAX_UUID } from 'uuid';
MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff'
Convert UUID string to array of bytes
str | A valid UUID String |
| returns | Uint8Array[16] |
| throws | TypeError if str is not a valid UUID |
[!NOTE] Ordering of values in the byte arrays used by
parse()andstringify()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
// ]
Convert array of bytes to UUID string
arr | Array-like collection of 16 values (starting from offset) between 0-255. |
[offset = 0] | Number Starting index in the Array |
| returns | String |
| throws | TypeError if a valid UUID string cannot be generated |
[!NOTE] Ordering of values in the byte arrays used by
parse()andstringify()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'
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 |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
| throws | Error 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'
Convert a UUID from version 1 to version 6
import { v1ToV6 } from 'uuid';
v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'
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."
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 |
| returns | UUID 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'
Create an RFC version 5 (namespace w/ SHA-1) UUID
name | String | Array |
namespace | String | 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 |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
[!NOTE] The RFC
DNSandURLnamespaces are available asv5.DNSandv5.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'
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'
Convert a UUID from version 6 to version 1
import { v6ToV1 } from 'uuid';
v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'
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 |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
Example:
import { v7 as uuidv7 } from 'uuid';
uuidv7(); // ⇨ '01941f29-7c00-73e4-a310-744d2167fc5b'
"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. Thevalidate()andversion()methods do work with such UUIDs, however.
Test a string to see if it is a valid UUID
str | String to validate |
| returns | true 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
Detect RFC version of a UUID
str | A valid UUID String |
| returns | Number The RFC version of the UUID |
| throws | TypeError 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
0for theNILUUID, and15for theMAXUUID.
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 UUIDsPrior 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:
options: Internal state is utilized to improve UUID uniqueness.options: Internal state is NOT used and, instead, appropriate defaults are applied as needed.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
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-get-random-valuesuuid. 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