Generate UUID in JavaScript
crypto.randomUUID() is native in all modern browsers and Node.js — zero dependencies, CSPRNG-backed UUID v4. Use the uuid package for v7 (time-ordered) and v5 (deterministic).
Quick Reference
| Version | Use Case | Sortable | Dependency |
|---|---|---|---|
| v4 | Random IDs, session tokens, client-side keys | No | None — crypto.randomUUID() |
| v7 | Time-ordered IDs, database PKs, event logs | Yes | npm install uuid |
| v5 | Deterministic IDs from a namespace + name | No | npm install uuid |
Primary Implementation
// No imports needed — crypto.randomUUID() is a native Web Crypto API method
// Generate a single UUID v4
const id = crypto.randomUUID();
console.log(id);
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"
// Generate multiple UUIDs
const ids = Array.from({ length: 5 }, () => crypto.randomUUID());
console.log(ids);
// Use as a typed variable (JSDoc)
/** @type {string} */
const sessionId = crypto.randomUUID();
// Check browser support before calling
function generateId() {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// Fallback for very old browsers (pre-2021)
throw new Error('crypto.randomUUID() not supported in this environment');
}
// Practical: attach to a fetch request as idempotency key
async function createOrder(payload) {
const idempotencyKey = crypto.randomUUID();
const response = await fetch('/api/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey,
},
body: JSON.stringify(payload),
});
return response.json();
}
All UUID Versions
UUID v4 — Random (Native, no deps)
// UUID v4: 122 bits of randomness, RFC 4122 compliant // Best for: session IDs, request IDs, anything where you just need a unique ID const id = crypto.randomUUID(); // → "550e8400-e29b-41d4-a716-446655440000"
UUID v7 — Time-ordered (requires uuid package)
// npm install uuid
import { v7 as uuidv7 } from 'uuid';
// UUID v7: millisecond-precision timestamp prefix + random suffix
// Best for: database primary keys (sorts chronologically), event logs
const id = uuidv7();
// → "018e8f6a-1b2c-7d3e-9f4a-5b6c7d8e9f0a"
// Note: IDs generated later will always sort after earlier ones
UUID v5 — Deterministic / Namespace-based
import { v5 as uuidv5 } from 'uuid';
// UUID v5: SHA-1 hash of namespace UUID + name string
// Same inputs always produce the same UUID — useful for deduplication
const DNS_NAMESPACE = uuidv5.DNS;
const id = uuidv5('example.com', DNS_NAMESPACE);
// → always "cfbff0d1-9375-5685-968c-48ce8b15ae17" for "example.com"
Real-World Use Cases
1. Client-side temporary record ID (optimistic UI)
// Optimistic UI: assign a UUID before the server responds
function addTodoOptimistically(text, setTodos) {
const tempId = crypto.randomUUID();
const newTodo = { id: tempId, text, status: 'pending' };
// Immediately update UI
setTodos(prev => [...prev, newTodo]);
// Then sync with server
fetch('/api/todos', {
method: 'POST',
body: JSON.stringify({ id: tempId, text }),
});
}
2. Idempotency key for API requests
// Prevent duplicate charges on payment retry
async function chargeCard(amount, cardToken) {
const key = crypto.randomUUID(); // generate once, reuse on retry
sessionStorage.setItem('payment_idempotency_key', key);
return fetch('/api/payments', {
method: 'POST',
headers: { 'Idempotency-Key': key },
body: JSON.stringify({ amount, cardToken }),
});
}
3. Unique localStorage / sessionStorage key
// Assign a 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;
}
const deviceId = getDeviceId();
console.log('Device:', deviceId);
Common Mistakes
Using Math.random() for IDs
Math.random() is not cryptographically secure and only produces ~53 bits of randomness. Collision probability is unacceptably high for any real ID system. Always use crypto.randomUUID().
Calling it in a non-secure context (HTTP)
crypto.randomUUID() is only available in secure contexts (HTTPS, localhost). On plain HTTP pages it will throw a TypeError. Always serve your app over HTTPS in production.
Building a UUID manually with string concatenation
Manually constructing UUID strings like `${hex}-${hex}-4${hex}...` is error-prone and almost always produces non-compliant UUIDs. Use the API.
Not checking browser support for legacy targets
crypto.randomUUID() was added in Chrome 92, Firefox 95, Safari 15.4 (2021–2022). If you target older browsers, add a feature check and fall back to the uuid npm package.
How It Works
crypto.randomUUID() generates a version 4 UUID as defined in RFC 4122. It fills 122 bits with cryptographically random data from the browser's CSPRNG (the same source used for crypto.getRandomValues()).
The remaining 6 bits are fixed: 4 bits encode the version (0100 = v4) and 2 bits encode the variant (10 = RFC 4122). This is why the third group always starts with 4 and the fourth group always starts with 8, 9, a, or b.
With 2^122 possible values (~5.3 × 10^36), the probability of a collision when generating 1 billion UUIDs per second for 100 years is astronomically small.
Output Example
f47ac10b-58cc-4372-a567-0e02b2c3d479
Best Practices
Use crypto.randomUUID() for all new browser code — it's native, fast, and requires no dependencies.
Use UUID v7 (via the uuid package) when you need IDs that sort chronologically — great for database PKs.
Store UUIDs as lowercase strings for consistency — some APIs are case-sensitive.
Performance
Native crypto.randomUUID() runs at roughly 5–10 million UUIDs/second in V8 (Chrome/Node). It's implemented in C++ and calls the OS CSPRNG directly.
The method is thread-safe — each call is independent. No shared state, no locking needed in Web Workers.
For bulk generation, Array.from({ length: n }, () => crypto.randomUUID()) is idiomatic and efficient.
Installation
UUID v4 (native)
# No installation needed
UUID v7 (npm)
npm install uuid
Browser support: Chrome 92+, Firefox 95+, Safari 15.4+, Edge 92+. Available in all secure contexts (HTTPS + localhost).
Security
Entropy source: The browser's CSPRNG, exposed via the Web Crypto API. On Chrome/V8 this maps to BCryptGenRandom on Windows and /dev/urandom on Linux/macOS.
Is it CSPRNG? Yes. The output is suitable for security-sensitive use cases like session tokens and CSRF tokens.
Caveat: Only available in secure contexts. Calling it over HTTP (non-localhost) throws a TypeError.