crypto-random-string, uuid, uuid-random, and uuidv4 are utilities for generating random data, but they serve distinct architectural purposes. crypto-random-string creates custom-length, URL-safe strings using cryptographically strong random number generators, ideal for tokens and secrets. uuid is the industry-standard, fully-featured library for generating RFC 4122 compliant Universally Unique Identifiers (UUIDs), supporting multiple versions (v1, v3, v4, v5). uuid-random and uuidv4 are lightweight, specialized packages focused solely on generating Version 4 UUIDs. While uuid offers broad compliance and tree-shaking capabilities for modern bundlers, the specialized packages provide minimalistic APIs for specific use cases, though some face maintenance or deprecation concerns.
In frontend and Node.js architecture, generating unique identifiers is a daily task. Whether you are creating session tokens, database keys, or temporary file names, the choice of library impacts security, bundle size, and standard compliance. We will compare crypto-random-string, uuid, uuid-random, and uuidv4 to help you decide which tool fits your specific engineering needs.
The most critical distinction lies in what these libraries produce. crypto-random-string generates arbitrary random strings, while the others generate strictly formatted UUIDs.
crypto-random-string creates a string of a specified length using cryptographically strong random numbers. It does not follow the UUID format (8-4-4-4-12 hex digits). This makes it perfect for secrets where structure doesn't matter, only entropy and length.
// crypto-random-string: Generate a 32-character URL-safe string
import cryptoRandomString from 'crypto-random-string';
const apiKey = cryptoRandomString({ length: 32 });
// Example output: 'x8f9...z2k1' (32 chars, no hyphens)
const hexToken = cryptoRandomString({ length: 16, type: 'hex' });
// Example output: 'a1b2c3d4e5f6g7h8'
uuid, uuid-random, and uuidv4 all generate UUIDs (Universally Unique Identifiers). Specifically, they focus on Version 4 (random) UUIDs, which follow the RFC 4122 standard format (xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx). This structure guarantees uniqueness across space and time without a central coordinator.
// uuid: Generate a standard v4 UUID
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();
// Example output: '550e8400-e29b-41d4-a716-446655440000'
// uuid-random: Generate a v4 UUID
import uuid from 'uuid-random';
const id = uuid();
// Example output: '550e8400-e29b-41d4-a716-446655440000'
// uuidv4: Generate a v4 UUID
import uuidv4 from 'uuidv4';
const id = uuidv4();
// Example output: '550e8400-e29b-41d4-a716-446655440000'
How you import and configure these libraries varies significantly, affecting both developer experience and bundle optimization.
uuid adopts a modular approach. You must import the specific version you need (e.g., v4, v1). This design enables modern bundlers to "tree-shake" (remove) unused code, keeping your final bundle small. It also supports advanced options like custom random number generators.
// uuid: Modular import for tree-shaking
import { v4 } from 'uuid';
// Advanced: Using a custom random function (rare but possible)
import { v4 } from 'uuid';
const myId = v4({ random: [/* 16 byte array */] });
crypto-random-string offers a flexible configuration object. You can define the exact length and restrict the character set (alphanumeric, hex, base64, or URL-safe). This flexibility is unmatched by the UUID libraries.
// crypto-random-string: Flexible configuration
import cryptoRandomString from 'crypto-random-string';
// URL-safe string (no + or /)
const token = cryptoRandomString({ length: 20, type: 'url-safe' });
// Alphanumeric only
const code = cryptoRandomString({ length: 6, characters: '0123456789' });
uuid-random and uuidv4 prioritize simplicity. They typically export a single function as the default export. There are no options to configure the random source or format; you get a standard v4 UUID and nothing else.
// uuid-random: Simple default export
import uuid from 'uuid-random';
const id = uuid(); // No options accepted
// uuidv4: Simple default export
import uuidv4 from 'uuidv4';
const id = uuidv4(); // No options accepted
A crucial architectural decision involves the long-term health of the dependency.
uuid is the gold standard. It is actively maintained, widely audited, and the go-to recommendation for enterprise applications. It has no deprecation warnings.
crypto-random-string is also well-maintained and relies on Node's built-in crypto module (or browser equivalents), ensuring high security standards.
uuid-random and uuidv4 occupy a risky space. While they function correctly today, they are often wrappers around older logic or duplicate functionality now native to the main uuid package. In the npm ecosystem, specialized single-purpose packages like uuidv4 are frequently deprecated in favor of the modular main package (uuid). Using them introduces a risk of future abandonment or security lag. If you see these in a legacy codebase, plan to migrate to uuid.
// β Risky: Relying on potentially stagnant packages
import uuidv4 from 'uuidv4';
// β
Safe: Using the actively maintained standard
import { v4 as uuidv4 } from 'uuid';
All four packages work in both Node.js and modern browsers, but their underlying mechanisms differ.
crypto-random-string explicitly leverages crypto.randomBytes in Node.js and crypto.getRandomValues in browsers. This ensures the output is cryptographically strong in any environment, making it safe for security tokens.
// crypto-random-string works seamlessly across environments
// It automatically detects the runtime and picks the secure RNG
import cryptoRandomString from 'crypto-random-string';
const secureToken = cryptoRandomString({ length: 32 });
uuid similarly detects the environment. In older browsers lacking native crypto support, it might fall back to less secure methods unless configured otherwise, but in modern stacks (React, Vue, Angular), it works out of the box with strong entropy.
uuid-random and uuidv4 generally rely on Math.random() in some implementations or older crypto shims. While often sufficient for non-security IDs (like tracking pixels), they may not meet the strict "cryptographically strong" requirement needed for authentication tokens without verifying their specific source code.
You need a secure, unpredictable string to email to a user. It doesn't need to be a UUID, just long and random.
crypto-random-stringimport cryptoRandomString from 'crypto-random-string';
const resetToken = cryptoRandomString({ length: 32, type: 'url-safe' });
// Send resetToken via email
You are designing a distributed database and need unique IDs for records that won't collide.
uuidimport { v4 as uuidv4 } from 'uuid';
const newUserId = uuidv4();
// Insert into database with id: newUserId
You need a quick ID to track a user's session in a browser cookie for analytics, not security.
uuid-random or uuidv4 (if already installed)uuid is still preferred for consistency.// Using uuid-random for a quick analytics ID
import uuid from 'uuid-random';
const sessionId = uuid();
document.cookie = `session_id=${sessionId}`;
| Feature | crypto-random-string | uuid | uuid-random | uuidv4 |
|---|---|---|---|---|
| Output Format | Custom String | RFC 4122 UUID | RFC 4122 UUID | RFC 4122 UUID |
| Configurability | High (Length, Chars) | Medium (Version, RNG) | None | None |
| Security Grade | Cryptographically Strong | Cryptographically Strong | Varies (Check Source) | Varies (Check Source) |
| Bundle Size | Small | Optimizable (Tree-shake) | Tiny | Tiny |
| Maintenance | Active | Active | Low / Stagnant | Low / Stagnant |
| Best For | Tokens, Secrets, Salts | DB Keys, Distributed IDs | Legacy, Simple Scripts | Legacy, Simple Scripts |
For security-critical strings like API keys, passwords, or salts, always choose crypto-random-string. Its ability to customize length and character sets while guaranteeing cryptographic strength makes it indispensable for auth flows.
For unique identifiers (database keys, request IDs), uuid is the definitive choice. Its modular architecture, strict adherence to standards, and active maintenance make it the only safe bet for scalable applications. Avoid uuid-random and uuidv4 in new projects; they solve a problem that uuid already solves better, without the risk of future deprecation.
Choose uuid for production-grade applications requiring RFC 4122 compliance, support for multiple UUID versions (v1, v3, v4, v5), or robust tree-shaking in modern bundlers like Webpack and Vite. It is the safest long-term bet for team projects due to its active maintenance, comprehensive test suite, and explicit separation of concerns via sub-imports.
Choose crypto-random-string when you need a random string of a specific length and character set (e.g., API keys, password reset tokens, or salts) rather than a standardized identifier format. It is the best choice for security-sensitive strings where UUID structure is unnecessary, and you require control over the output length and character inclusion.
Avoid choosing uuid-random for new critical projects. While it provides a simple API for generating v4 UUIDs, it lacks the extensive RFC compliance features, versioning options, and active maintenance guarantees of the main uuid package. Only consider it for extremely lightweight scripts where bundle size is the absolute highest priority and standard compliance is irrelevant.
Avoid choosing uuidv4 for new projects as it is often considered redundant given the modular exports of the main uuid package. While it offers a direct default export for v4 generation, relying on it adds an extra dependency for functionality that is natively available in uuid. Use it only if you are maintaining a legacy codebase that already depends on it.
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