Developer Lab · JavaScript
Generate UUID in JavaScript
To generate a UUID in JavaScript, call crypto.randomUUID(). It is built into modern browsers and Node.js, requires no dependencies, and returns an RFC 4122 version 4 UUID backed by a cryptographically secure random number generator. For time-ordered v7 or deterministic v5 IDs, use the uuid npm package.
Quick Answer
Production ready// One line - no imports required
const id = crypto.randomUUID();
console.log(id);
// → "550e8400-e29b-41d4-a716-446655440000"
Step-by-Step Guide
Follow these four steps to generate, extend, and safely store UUIDs in any JavaScript runtime.
-
1
Verify your environment
In browsers,
crypto.randomUUID()requires a secure context (HTTPS or localhost). In Node.js, use version 19+ for the global API, orimport { randomUUID } from 'node:crypto'on 14.17+.javascriptfunction canGenerateUUID() { return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'; } -
2
Generate a UUID v4
Call
crypto.randomUUID()anywhere you have access to the Web Crypto API. Each call is independent and thread-safe.javascriptconst sessionId = crypto.randomUUID(); const batch = Array.from({ length: 10 }, () => crypto.randomUUID()); -
3
Install uuid for v7 or v5
Native APIs only produce v4. Install
uuidwhen you need sortable v7 or deterministic v5 identifiers.bashnpm install uuid -
4
Validate and store
Validate external UUIDs at API boundaries. Store as lowercase strings in JavaScript; use binary UUID columns in your database when possible.
javascriptconst id = crypto.randomUUID().toLowerCase(); if (!isUUID(incomingId)) throw new Error('Invalid UUID');
Quick Reference
Choose the right UUID version and method for your use case.
| Version | Method | Sortable | RFC | Dependency | Best for |
|---|---|---|---|---|---|
| v4 | crypto.randomUUID() | No | 4122 | None | Session tokens, client IDs, general randomness |
| v7 | uuidv7() | Yes | 9562 | uuid package | Database PKs, event logs, chronological sorting |
| v5 | uuidv5(name, namespace) | No | 4122 | uuid package | Deterministic IDs from namespace + name |
| v1 / v3 / v6 | uuid package | v1/v6 yes | 4122 / 9562 | uuid package | Legacy systems, MAC-based or MD5 namespaces |
Environment Compatibility
crypto.randomUUID() availability across JavaScript runtimes.
| Runtime | v4 support | Notes |
|---|---|---|
| Chrome / Edge | 92+ | Secure context required in production |
| Firefox | 95+ | Same secure-context rule |
| Safari | 15.4+ | iOS 15.4+ |
| Node.js | 14.17+ (import), 19+ (global) | See Node.js guide |
| Deno | 1.x+ | Global crypto.randomUUID() |
| Bun | 1.x+ | Web Crypto compatible |
| Web Workers | Yes | crypto global available in dedicated workers |
| Service Workers | Yes | Secure context only |
All UUID Versions
UUID v4 - Random (native)
// 122 bits of CSPRNG randomness, RFC 4122 compliant
const id = crypto.randomUUID();
// → "550e8400-e29b-41d4-a716-446655440000"UUID v7 - Time-ordered (uuid package)
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
// → "018e8f6a-1b2c-7d3e-9f4a-5b6c7d8e9f0a"
// Later IDs sort after earlier ones (RFC 9562)UUID v5 - Deterministic namespace
import { v5 as uuidv5 } from 'uuid';
const id = uuidv5('example.com', uuidv5.DNS);
// → always "cfbff0d1-9375-5685-968c-48ce8b15ae17"UUID v1 / v3 / v6 - uuid package
import { v1 as uuidv1, v3 as uuidv3, v6 as uuidv6 } from 'uuid';
uuidv1(); // timestamp + MAC-based node
uuidv3('hello', uuidv3.URL); // MD5 namespace hash
uuidv6(); // reordered v1 for better DB locality (RFC 9562)Validate and Parse UUIDs
TypeScript types do not validate runtime input. Always check UUIDs from HTTP requests, query params, and user input.
const UUID_RE =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
function isUUID(value) {
return typeof value === 'string' && UUID_RE.test(value);
}
function normalizeUUID(value) {
if (!isUUID(value)) throw new TypeError('Invalid UUID');
return value.toLowerCase();
}
// v5 inputs: use stable lowercase names; URLs should be canonical
const name = 'example.com';
const id = uuidv5(name, uuidv5.DNS);Real-World Use Cases
Optimistic UI (client-side temp IDs)
function addTodoOptimistically(text, setTodos) {
const tempId = crypto.randomUUID();
setTodos((prev) => [...prev, { id: tempId, text, status: 'pending' }]);
fetch('/api/todos', {
method: 'POST',
body: JSON.stringify({ id: tempId, text }),
});
}Idempotency keys for API requests
async function chargeCard(amount, cardToken) {
const key = crypto.randomUUID();
sessionStorage.setItem('payment_idempotency_key', key);
return fetch('/api/payments', {
method: 'POST',
headers: { 'Idempotency-Key': key },
body: JSON.stringify({ amount, cardToken }),
});
}Persistent anonymous device ID
function getDeviceId() {
const key = 'device_id';
let id = localStorage.getItem(key);
if (!id) {
id = crypto.randomUUID();
localStorage.setItem(key, id);
}
return id;
}WebSocket correlation IDs
const ws = new WebSocket('wss://api.example.com/ws');
const connectionId = crypto.randomUUID();
ws.addEventListener('open', () => {
ws.send(JSON.stringify({ type: 'hello', connectionId }));
});IndexedDB record keys
async function saveDraft(db, content) {
const id = crypto.randomUUID();
const tx = db.transaction('drafts', 'readwrite');
tx.objectStore('drafts').put({ id, content, updatedAt: Date.now() });
await tx.done;
return id;
}Distributed tracing correlation IDs
const correlationId = crypto.randomUUID();
console.info(JSON.stringify({
level: 'info',
correlationId,
message: 'Order created',
orderId: crypto.randomUUID(),
}));UUID v4 vs v7 Decision Guide
Use v4 by default. Switch to v7 when insert order and index locality matter at database scale.
- →UUID v7 Generator - interactive v7 generation and export.
- →Format comparison - v4 vs v7 vs ULID vs NanoID.
- →TypeScript guide - branded UUID types and Zod validation.
How UUID v4 Works
crypto.randomUUID() fills 122 bits from the OS CSPRNG. Six bits are fixed: four encode version 4 (0100) and two encode the RFC 4122 variant (10).
f47ac10b-58cc-4372-a567-0e02b2c3d479
- f47ac10b
- 32 random bits
- 58cc
- 16 random bits
- 4372
- version 4 + 12 random bits
- a567
- variant 10 + 14 random bits
- 0e02b2c3d479
- 48 random bits
With 2^122 possible values, collision risk is negligible for any practical application. The birthday bound for a 50% collision chance requires generating roughly 2.6 billion billion UUIDs.
Common Mistakes
Using Math.random() for IDs
Math.random() is not cryptographically secure and provides only ~53 bits of entropy. Always use crypto.randomUUID().
Calling crypto.randomUUID() over plain HTTP
Non-secure contexts throw TypeError. Use HTTPS in production or localhost during development.
Building UUIDs with string concatenation
Manual templates often violate version/variant bit rules. Use the platform API or the uuid package.
Skipping browser support checks for legacy targets
Pre-2021 browsers lack native support. Feature-detect and fall back to the uuid package when needed.
Using v4 as a database PK at very large scale
Random v4 inserts fragment B-tree indexes. Above ~10M rows, consider UUID v7 for chronological insert locality.
Coercing UUIDs to numbers
UUIDs exceed JavaScript's safe integer range. Keep them as strings end to end.
Best Practices, Performance, and Security
Best practices
Use crypto.randomUUID() for all new v4 code.
Store UUIDs as lowercase strings for consistent comparison.
Use UUID v7 for time-ordered database primary keys (RFC 9562).
Performance
Native crypto.randomUUID() typically generates millions of IDs per second in V8 (exact throughput varies by OS CSPRNG and hardware). Each call is independent with no shared mutable state.
Bulk generation: Array.from({ length: n }, () => crypto.randomUUID()) is idiomatic and efficient.
Security
Entropy source: OS CSPRNG via Web Crypto. On Windows this maps to BCryptGenRandom; on Linux and macOS to /dev/urandom.
CSPRNG suitable for: session tokens, CSRF tokens, idempotency keys, and client-side correlation IDs.
Caveat: Secure context required in browsers. Never use Math.random() for security-sensitive identifiers.
Installation
UUID v4 (native)
# No installation neededAvailable globally in Node 19+, browsers since 2021, Deno, and Bun.
uuid package (v7, v5, v1, v3, v6)
npm install uuid
# or: pnpm add uuid / yarn add uuid / bun add uuid// ESM
import { v7 as uuidv7 } from 'uuid';
// CommonJS
const { v4: uuidv4 } = require('uuid');Frequently Asked Questions
How do I generate a UUID in JavaScript?
Call crypto.randomUUID() with no imports. It returns an RFC 4122 version 4 UUID string like "550e8400-e29b-41d4-a716-446655440000". For time-ordered v7 or deterministic v5 UUIDs, install the uuid package and use uuidv7() or uuidv5().
Is crypto.randomUUID() cryptographically secure?
Yes. crypto.randomUUID() draws from the same CSPRNG as crypto.getRandomValues(), suitable for session tokens, CSRF tokens, and idempotency keys. Do not use Math.random() for identifiers.
Does crypto.randomUUID() work in Node.js?
Yes. Node.js 19+ exposes crypto.randomUUID() on the global crypto object. On Node.js 14.17 through 18, import it: import { randomUUID } from "node:crypto".
What is the difference between UUID v4 and v7 in JavaScript?
UUID v4 (crypto.randomUUID()) is fully random and not sortable. UUID v7 (via the uuid package) embeds a millisecond timestamp in the leading bits, so IDs sort chronologically. Use v7 for database primary keys at scale; use v4 for general-purpose random IDs.
When should I use the uuid npm package?
Use the uuid package when you need UUID v7 (time-ordered), v5 or v3 (deterministic from a namespace), v1 (timestamp + MAC), or v6. Native crypto.randomUUID() only generates v4.
Why does crypto.randomUUID() throw a TypeError on HTTP?
The Web Crypto API is restricted to secure contexts: HTTPS and localhost. On plain HTTP (non-localhost), crypto.randomUUID() throws TypeError. Serve production apps over HTTPS.
How do I validate a UUID string in JavaScript?
Use a regex test: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value). Normalize to lowercase before comparing or storing.
Does crypto.randomUUID() work in Web Workers?
Yes. Web Workers have access to the crypto global and crypto.randomUUID() works the same as on the main thread, including the secure-context requirement.
Should I store UUIDs as strings or binary in JavaScript apps?
In JavaScript, UUIDs are strings. When persisting to a database, prefer native binary UUID types (PostgreSQL UUID, MySQL BINARY(16)) over VARCHAR(36) for smaller indexes and faster comparisons.
What RFC standards apply to JavaScript UUID generation?
crypto.randomUUID() produces RFC 4122 version 4 UUIDs. UUID v7 follows RFC 9562 (May 2024). The uuid npm package implements RFC 4122 and RFC 9562 versions.
Key definitions
- UUID
- 128-bit universally unique identifier, usually shown as 36 hex characters with hyphens.
- CSPRNG
- Cryptographically secure pseudo-random number generator. The entropy source behind crypto.randomUUID().
- Secure context
- Browser environments where Web Crypto is available: HTTPS origins and localhost.
- RFC 4122
- IETF standard defining UUID versions 1 through 5. Version 4 is random.