UUID v4 genereren in JavaScript β Complete gids
Gebruik de gratis UUID v4 Generator direct in je browser β geen installatie nodig.
UUID v4 Generator online uitproberen βElke JavaScript-applicatie heeft uiteindelijk unieke identifiers nodig β sessietokens, databaserijen, idempotentiesleutels voor betaal-API's, correlatie-ID's voor gedistribueerde tracing. De eenvoudigste manier om UUID v4 te genereren in JavaScript is vandaag crypto.randomUUID(): geen afhankelijkheden, één regel, cryptografisch veilig. UUID v4 wordt veel gebruikt juist omdat er geen coΓΆrdinatie tussen services nodig is β client en server kunnen beide onafhankelijk ID's genereren zonder risico op botsingen. Deze gids behandelt die ingebouwde API, het uuid npm-pakket, validatie β alles op Node.js 19+ en moderne browsers. Voor een no-code-optie genereert de UUID v4 Generator op ToolDeck direct conforme identifiers.
- βcrypto.randomUUID() is ingebouwd in browsers en Node.js β geen afhankelijkheden, één regel code.
- βUUID v4 is een 128-bit willekeurige identifier: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y is 8, 9, a of b).
- βValideer met /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i β controleert versie- en variantbits.
- βHet uuid npm-pakket voegt ondersteuning voor v1, v3, v5 en v7 toe wanneer je meer nodig hebt dan willekeurige ID's.
- βGeef voor databaseprimaire sleutels de voorkeur aan UUID v7 (tijdgeordend) boven v4 (willekeurig) om indexfragmentatie te verminderen.
Wat is UUID v4?
Een UUID (Universally Unique Identifier) versie 4 is een 128-bit willekeurige identifier opgemaakt als 32 hexadecimale cijfers gescheiden door vier koppeltekens: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. De 4 op positie 15 geeft de versie aan. Het y-teken op positie 20 is een van 8, 9, a of b (de RFC 4122-variant). De overige 122 bits zijn willekeurig. UUID v4 is de meest gebruikte versie in JavaScript-applicaties omdat er geen coΓΆrdinatie tussen systemen nodig is β je kunt ID's onafhankelijk op client en server genereren zonder je zorgen te maken over botsingen.
// Geen identifier
const event = { action: "user.login", ts: 1711824000 };// Met UUID v4
const event = {
id: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
action: "user.login",
ts: 1711824000
};crypto.randomUUID() β De native JavaScript-aanpak
crypto.randomUUID() is beschikbaar in Chrome 92+, Firefox 95+, Safari 15.4+ en Node.js 19+ (met experimentele ondersteuning vanaf Node.js 14.17.0 via globalThis.crypto). Het geeft een kleine-letters 36-tekens UUID v4-string terug. In browser-JavaScript is geen import nodig. In Node.js kun je het direct aanroepen op het globale crypto-object of het expliciet importeren uit de node:crypto-module.
// Werkt in elke moderne browser β geen buildstap, geen bundler
const requestId = crypto.randomUUID();
console.log(requestId);
// "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
// Gebruik het overal waar je een unieke identifier nodig hebt
const telemetryEvent = {
event_id: crypto.randomUUID(),
action: "checkout.started",
session_id: crypto.randomUUID(),
timestamp: Date.now(),
cart_total_cents: 14999,
};
console.log(JSON.stringify(telemetryEvent, null, 2));// Benadering 1: globale crypto (Node.js 19+)
const orderId = crypto.randomUUID();
console.log(orderId);
// "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
// Benadering 2: expliciete import uit node:crypto
import { randomUUID } from 'node:crypto';
const correlationId = randomUUID();
console.log(correlationId);
// "f7e6d5c4-b3a2-4190-8f7e-6d5c4b3a2190"Feature-detectie van crypto.randomUUID is de moeite waard als je code mogelijk in oudere browsers of embedded WebViews wordt uitgevoerd. De controle bestaat uit één typeof-bewaker:
function generateUUIDv4() {
// Geef de voorkeur aan de native API als die beschikbaar is
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// Handmatige fallback met getRandomValues (zie volgende sectie)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// Stel versie (4) en variant (RFC 4122) in
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10xx
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return [
hex.slice(0, 4).join(''),
hex.slice(4, 6).join(''),
hex.slice(6, 8).join(''),
hex.slice(8, 10).join(''),
hex.slice(10, 16).join(''),
].join('-');
}
console.log(generateUUIDv4());
// "9b2e4f1a-7c3d-4e8f-a5b6-0d2c1e9f8a7b"crypto.randomUUID() altijd beschikbaar. Het geeft een fout op niet-beveiligde HTTP-pagina's in sommige browsers. Als je applicatie soms op gewone HTTP draait tijdens ontwikkeling, handelt de getRandomValues-fallback hierboven dat geval af.UUID v4 genereren zonder een library
Soms kun je niet vertrouwen op crypto.randomUUID() β misschien richt je je op een WebView die de crypto-API verwijdert, of wil je begrijpen wat er onder de motorkap gebeurt. De handmatige aanpak gebruikt crypto.getRandomValues() (beschikbaar sinds IE 11) om 16 bytes met willekeurige gegevens te vullen, en past vervolgens twee bitmask-bewerkingen toe om de versie- en variantvelden in te stellen. Deze twee bewerkingen zijn het enige verschil tussen UUID v4 en een puur willekeurige byte-string.
function uuidv4Manual() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// Set version: bits 12β15 of byte 6 = 0100 (version 4)
bytes[6] = (bytes[6] & 0x0f) | 0x40;
// Set variant: bits 6β7 of byte 8 = 10 (RFC 4122)
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return (
hex.slice(0, 4).join('') + '-' +
hex.slice(4, 6).join('') + '-' +
hex.slice(6, 8).join('') + '-' +
hex.slice(8, 10).join('') + '-' +
hex.slice(10, 16).join('')
);
}
const traceId = uuidv4Manual();
console.log(traceId);
// "e4d7c2a1-3f9b-48e5-a612-9d8c7b6a5f4e"
// Controleer of het UUID v4-validatie doorstaat
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
console.log(UUID_V4_RE.test(traceId)); // trueMath.random() om UUID's te genereren. Het is niet cryptografisch veilig, de uitvoerperiode is te kort, en sommige engines produceren voorspelbare reeksen. Gebruik altijd crypto.getRandomValues() of crypto.randomUUID().Het uuid npm-pakket β Ondersteuning voor meerdere versies
Het uuid pakket op npm is de standaard UUID-bibliotheek voor JavaScript geweest voordat crypto.randomUUID() bestond. Het is nog steeds zinvol in drie situaties: je hebt UUID-versies anders dan v4 nodig (v1, v3, v5, v7), je richt je op runtimes ouder dan Node.js 14.17.0, of je wilt de validate en parse hulpfuncties. Voor gewone UUID v4 op een moderne runtime is de native API voldoende en zou ik de afhankelijkheid overslaan.
npm install uuid
import { v4 as uuidv4, validate, version } from 'uuid';
// Generate a UUID v4
const paymentId = uuidv4();
console.log(paymentId);
// "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
// Validate any UUID string
console.log(validate(paymentId)); // true
console.log(validate("not-a-uuid")); // false
// Detect the version of a UUID
console.log(version(paymentId)); // 4
// Generate a batch for seeding a test database
const testAccounts = Array.from({ length: 5 }, () => ({
account_id: uuidv4(),
plan: "starter",
created_at: new Date().toISOString(),
}));
console.log(testAccounts);uuid-pakket gebruikt intern crypto.getRandomValues() in browsers en crypto.randomBytes() in Node.js, zodat de entropiebron identiek is aan de native API. Het verschil zijn alleen de extra hulpfuncties en ondersteuning voor meerdere versies.Als je liever helemaal geen code schrijft, probeer dan de UUID v4 Generator β het genereert RFC 4122-conforme v4-identifiers direct in je browser met één klik.
Deterministische UUID's β UUID v5 genereren vanuit een string
UUID v4 is per definitie willekeurig β het twee keer aanroepen geeft altijd verschillende resultaten. Soms heb je het tegenovergestelde nodig: dezelfde invoerstring moet altijd dezelfde UUID produceren. Dat is wat UUID v5 doet. Het hasht een naamruimte-UUID en een invoerstring met SHA-1, en formatteert het resultaat als een UUID. Zelfde naamruimte + zelfde invoer = zelfde uitvoer, altijd, op elke machine. Dit is handig voor het afleiden van stabiele ID's van URL's, e-mailadressen of elke string die al een resource identificeert.
import { v5 as uuidv5 } from 'uuid';
// Built-in namespace for URLs (RFC 4122)
const URL_NAMESPACE = uuidv5.URL;
// "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
// Same URL always produces the same UUID
const pageId1 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
const pageId2 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
console.log(pageId1 === pageId2); // true
console.log(pageId1);
// "a6e4e1c0-7e23-5d3b-8f14-9c2a1b3d5e7f"
// Custom namespace for your application
const APP_NAMESPACE = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
const tenantId = uuidv5("acme-corp", APP_NAMESPACE);
console.log(tenantId);
// "d4735e3a-265b-564e-8f32-7a1b2c3d4e5f"Korte noot: UUID v3 doet hetzelfde maar met MD5 in plaats van SHA-1. Geef de voorkeur aan v5 voor nieuwe projecten. MD5 heeft bekende botsingsfouten, en hoewel dat voor ID-generatie niet zo relevant is, is er geen reden om het te kiezen boven SHA-1 als beide beschikbaar zijn.
Referentie voor crypto.randomUUID() en gerelateerde API's
De native crypto.randomUUID() accepteert geen argumenten β het geeft een string terug en niets anders. Gebruik het wanneer je RFC 4122- conforme identifiers nodig hebt zonder afhankelijkheden. Wanneer je ruwe willekeurige bytes nodig hebt in plaats van een geformatteerde UUID-string β bijvoorbeeld om een typed array te vullen of een sleutel af te leiden β gebruik dan direct crypto.getRandomValues(). De gerelateerde API's die relevant zijn voor UUID-werk worden hieronder vermeld.
Uitsplitsing van het UUID v4 regex-patroon:
UUID v4 valideren met Regex
Controleren of een string een correcte UUID v4 is, komt constant voor β inkomende API-verzoekinhoud, URL-parameters, webhook-payloads. Een handgemaakte regex is de juiste keuze als je geen afhankelijkheden wilt en alleen v4 valideert. Als je het uuid pakket al gebruikt, geef dan de voorkeur aan de validate() export β het verwerkt alle UUID-versies en is minder foutgevoelig dan een aangepast patroon onderhouden. De regex /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i controleert zowel de versienibble (moet 4 zijn) als de variantnibble (moet 8, 9, a of b zijn). Gebruik RegExp.prototype.test() voor booleaanse controles en .match() wanneer je een UUID uit omliggende tekst wilt extraheren.
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
function isUUIDv4(str) {
return UUID_V4_RE.test(str);
}
// Valid UUID v4
console.log(isUUIDv4("9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d")); // true
// UUID v1 β version nibble is 1, not 4
console.log(isUUIDv4("550e8400-e29b-11d4-a716-446655440000")); // false
// UUID v7 β version nibble is 7
console.log(isUUIDv4("018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b")); // false
// Malformed strings
console.log(isUUIDv4("not-a-uuid")); // false
console.log(isUUIDv4("")); // false
console.log(isUUIDv4("9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d")); // false (no hyphens)
// Extract UUID from a larger string
const logLine = 'Request req_id=9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d failed with 503';
const match = logLine.match(/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i);
console.log(match?.[0]);
// "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"UUID's genereren en koppelen vanuit bestand en API-respons
In de praktijk roep je crypto.randomUUID() zelden geΓ―soleerd aan. Twee patronen komen constant voor: ID's toewijzen aan records voordat ze naar een database worden geschreven, en correlatie-ID's koppelen aan uitgaande API-verzoeken zodat je een verzoek door services kunt volgen in je logs.
NDJSON-bestand lezen β UUID's toewijzen β Terugschrijven
import { readFileSync, writeFileSync } from 'node:fs';
import { randomUUID } from 'node:crypto';
function assignIds(inputPath, outputPath) {
const lines = readFileSync(inputPath, 'utf-8')
.split('\n')
.filter(line => line.trim());
const records = lines.map(line => {
try {
const record = JSON.parse(line);
if (!record.id) {
record.id = randomUUID();
}
return JSON.stringify(record);
} catch (err) {
console.error(`Skipping malformed line: ${err.message}`);
return null;
}
}).filter(Boolean);
writeFileSync(outputPath, records.join('\n') + '\n');
console.log(`Assigned IDs to ${records.length} records β ${outputPath}`);
}
assignIds('warehouse-products.ndjson', 'warehouse-products-with-ids.ndjson');
// Assigned IDs to 1284 records β warehouse-products-with-ids.ndjsonCorrelatie-ID koppelen aan uitgaand API-verzoek
import { randomUUID } from 'node:crypto';
async function createShipment(orderPayload) {
const correlationId = randomUUID();
try {
const response = await fetch('https://api.logistics.dev/v2/shipments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Correlation-ID': correlationId,
'X-Idempotency-Key': randomUUID(),
},
body: JSON.stringify(orderPayload),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Shipment API returned ${response.status}: ${errorBody}`);
}
const result = await response.json();
console.log(`Shipment created: ${result.shipment_id} (correlation: ${correlationId})`);
return result;
} catch (err) {
console.error(`[correlation:${correlationId}] Shipment failed: ${err.message}`);
throw err;
}
}
await createShipment({
order_id: "ord_8a3f91bc",
destination: { city: "Amsterdam", state: "NH", zip: "1012 AB" },
items: [{ sku: "WH-7291", quantity: 2, weight_kg: 1.4 }],
});UUID-generatie via de opdrachtregel
Je hebt niet altijd een script nodig. Node.js kan een UUID direct vanuit de opdrachtregel genereren, wat handig is voor shellscripts, CI-pipelines en snelle ad-hoctests. De -e-vlag evalueert één expressie.
# Single UUID node -e "console.log(crypto.randomUUID())" # 3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f # Five UUIDs at once node -e "for(let i=0;i<5;i++) console.log(crypto.randomUUID())" # Generate and assign to a shell variable export REQUEST_ID=$(node -e "process.stdout.write(crypto.randomUUID())") echo "Request ID: $REQUEST_ID" # Use npx uuid (if you have the package installed globally or want a one-off) npx uuid v4 # 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed
# Open any browser DevTools console and type: crypto.randomUUID() # "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
uuidgen vooraf geΓ―nstalleerd op macOS en de meeste Linux- distributies. Het genereert standaard UUID v4 op moderne systemen.Krachtig alternatief β nanoid
Als je duizenden ID's per seconde genereert en het 36-tekens UUID-formaat geen harde vereiste is, overweeg dan nanoid. Het is 2x sneller dan uuid.v4(), produceert standaard een 21-tekens URL-veilige ID en weegt na minificatie ongeveer 1 KB. De uitvoer is geen UUID β het is een ID met een aangepast alfabet β gebruik het dus niet waar RFC 4122- conformiteit vereist is (database UUID-kolommen, API's die het UUID-formaat valideren, OpenTelemetry trace-ID's). Maar voor interne correlatie-ID's, React-componentsleutels en URL-slugs is het een goede keuze.
npm install nanoid
import { nanoid, customAlphabet } from 'nanoid';
// Default: 21-char URL-safe ID (A-Za-z0-9_-)
const trackingCode = nanoid();
console.log(trackingCode);
// "V1StGXR8_Z5jdHi6B-myT"
// Custom length
const shortCode = nanoid(10);
console.log(shortCode);
// "IRFa-VaY2b"
// Custom alphabet β numbers only, 12 digits
const numericId = customAlphabet('0123456789', 12);
console.log(numericId());
// "839274651023"
// Custom alphabet β hex only, 32 chars (same entropy as UUID v4 without hyphens)
const hexId = customAlphabet('0123456789abcdef', 32);
console.log(hexId());
// "4f8a1b2c3d7e9f0a5b6c8d1e2f3a4b5c"Terminaluitvoer met syntaxismarkering
Het debuggen van UUID-zware applicaties betekent staren naar muren van hexadecimale strings in de terminal. Kleurcodering helpt. De chalk bibliotheek (of de nieuwere ingebouwde node:util styleText in Node.js 21.7+) laat je UUID's in loguitvoer markeren zodat ze opvallen tussen omringende tekst.
import chalk from 'chalk';
import { randomUUID } from 'node:crypto';
function logEvent(action, metadata = {}) {
const eventId = randomUUID();
const timestamp = new Date().toISOString();
console.log(
chalk.gray(timestamp),
chalk.cyan(eventId),
chalk.white(action),
Object.keys(metadata).length
? chalk.dim(JSON.stringify(metadata))
: ''
);
}
logEvent('shipment.created', { order_id: 'ord_8a3f', carrier: 'fedex' });
logEvent('payment.captured', { amount_cents: 14999, currency: 'USD' });
logEvent('webhook.delivered', { endpoint: 'https://hooks.acme.dev/orders' });
// 2026-03-27T10:15:00.000Z a1b2c3d4-... shipment.created {"order_id":"ord_8a3f",...}Korte unieke ID's genereren in JavaScript
Een 36-tekens UUID is soms te lang β URL-slugs, QR-codegegevens, sms-berichten en ingebedde hardwareprotocollen hebben allemaal lengtebeperkingen.
import { randomUUID } from 'node:crypto';
// 1. Strip hyphens from UUID v4 β 32-char hex string
const hex32 = randomUUID().replaceAll('-', '');
console.log(hex32);
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f" (32 chars)
// 2. Base64-encode 16 random bytes β 22-char string (URL-safe)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
const base64Id = Buffer.from(bytes)
.toString('base64url')
.replace(/=+$/, '');
console.log(base64Id);
// "Pj8akksNTY6fEnarPIvR" (22 chars, 128 bits of entropy)
// 3. nanoid at custom length
import { nanoid } from 'nanoid';
const short12 = nanoid(12);
console.log(short12);
// "V1StGXR8_Z5j" (12 chars, ~71 bits of entropy)De wiskundige berekening van botsingskansen: een 12-tekens nanoid (standaard alfabet van 64 tekens) geeft ruwweg 71 bits entropie. Bij 1.000 ID's per seconde heb je ongeveer 116 jaar nodig om een kans van 1% op een botsing te bereiken. Voor de meeste toepassingen is dat meer dan genoeg. Als je miljoenen ID's per dag genereert, gebruik dan de volledige UUID of nanoid met minimaal 21 tekens.
UUID v7 β Tijdgeordend alternatief voor v4
UUID v7 (gedefinieerd in RFC 9562) slaat een 48-bit Unix-millisecondentimestamp op in het eerste segment, gevolgd door willekeurige bits. Het resultaat is een UUID die lijkt op v4 maar chronologisch sorteert. Dit maakt het een betere keuze dan v4 voor databaseprimaire sleutels: nieuwe rijen landen altijd aan het einde van de B-tree-index in plaats van op willekeurige posities, wat paginasplitsingen en fragmentatie vermindert. In projecten waar ik tijdgeordende ID's nodig heb voor een Postgres-tabel, schakel ik meteen over naar v7 β het prestatieverschil in indexen is meetbaar op schaal. De UUID v7 Generator op ToolDeck toont de ingebedde timestamp voor elke v7 UUID.
import { v7 as uuidv7 } from 'uuid';
// Generate three UUID v7 values β notice they sort chronologically
const id1 = uuidv7();
const id2 = uuidv7();
const id3 = uuidv7();
console.log(id1);
// "018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b"
console.log(id2);
// "018e4a0c-5b40-7e34-9c2d-1e4f5a6b7c8d"
console.log(id3);
// "018e4a0c-5b41-7f56-ae3f-2a5b6c7d8e9f"
// They sort lexicographically by creation time
console.log([id3, id1, id2].sort());
// [id1, id2, id3] β chronological order preserved
// Use v4 for tokens where timing should not be leaked
import { v4 as uuidv4 } from 'uuid';
const sessionToken = uuidv4(); // fully random, no timing infouuid-pakket ondersteunt v7 vanaf versie 9.0.0. Als je een oudere versie gebruikt, voer dan npm install uuid@latest uit om te upgraden.UUID v4 in de browser zonder een buildstap
Geen bundler, geen npm, geen transpiler. Gewoon een normaal HTML-bestand. Dit is de eenvoudigste manier om een UUID te genereren in client-side JavaScript. Het werkt omdat crypto.randomUUID() een ingebouwde browser-API is.
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>UUID Generator</title></head>
<body>
<p>Your UUID: <strong id="output"></strong></p>
<button onclick="document.getElementById('output').textContent = crypto.randomUUID()">
Generate
</button>
<script>
// Generate one on page load
document.getElementById('output').textContent = crypto.randomUUID();
</script>
</body>
</html>Dat is het hele bestand. Geen CDN-imports, geen scripttags die libraries inladen. Voor iets complexer β batchgeneratie, validatie, deterministische ID's β heb je het uuid pakket of de handmatige fallback uit eerder nodig. Maar voor een snelle prototype of intern hulpmiddel is dit alles wat je nodig hebt.
Veelgemaakte fouten
Ik heb het Math.random() UUID-patroon vaker dan ik zou willen vanuit oude blogposts in productiecode zien worden gekopieerd. De fouten die deze patronen introduceren zijn stil: geen runtime-fout, alleen subtiel verkeerd gedrag dat later onder belasting of bij beveiligingsreviews naar boven komt.
Probleem: Math.random() is niet cryptografisch veilig. De uitvoer is voorspelbaar in sommige engines, en de lage entropie maakt botsingen veel waarschijnlijker dan met een correcte CSPRNG.
Oplossing: Gebruik altijd crypto.randomUUID() of crypto.getRandomValues(). Beide gebruiken de CSPRNG van het besturingssysteem.
// INSECURE β predictable, low entropy
function badUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
c => {
const r = Math.random() * 16 | 0;
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
}
);
}// SECURE β uses the OS CSPRNG
const id = crypto.randomUUID();
// Or if you need a manual fallback:
function secureUuid() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const h = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return `${h.slice(0,4).join('')}-${h.slice(4,6).join('')}-${h.slice(6,8).join('')}-${h.slice(8,10).join('')}-${h.slice(10).join('')}`;
}Probleem: crypto.randomUUID() geeft kleine hexadecimale letters terug, maar UUID's van andere systemen (databases, API's, gebruikersinvoer) kunnen hoofdletters gebruiken. Directe ===-vergelijking mislukt als de hoofdletters verschillen.
Oplossing: Normaliseer beide kanten naar kleine letters voordat je vergelijkt.
const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D"; // uppercase from API
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"; // lowercase from crypto
if (fromApi === local) { /* never runs */ }const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D";
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
if (fromApi.toLowerCase() === local.toLowerCase()) {
// matches correctly
}Probleem: Sommige UUID-bibliotheken (vooral in andere talen) geven UUID-objecten terug. In JavaScript breekt het per ongeluk inpakken van een UUID-string in een object gelijkheidscontroles, JSON-serialisatie en databasezoekopdrachten.
Oplossing: Sla UUID's altijd op als gewone strings en geef ze zo door. Als een bibliotheek een object teruggeeft, roep dan direct .toString() aan of open de string-eigenschap.
// Creating unnecessary wrapper
class UUID {
constructor(value) { this.value = value; }
}
const id = new UUID(crypto.randomUUID());
console.log(id === id); // true, but...
console.log(JSON.stringify({ id })); // {"id":{"value":"..."}}// Just use a string
const id = crypto.randomUUID();
console.log(JSON.stringify({ id }));
// {"id":"3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"}Probleem: UUID v4 is volledig willekeurig. Sorteren op UUID v4 geeft willekeurige volgorde, niet aanmaaksvolgorde. Dit leidt tot onvoorspelbare paginering, verwarrende beheerinterfaces en slechte databaseindexprestaties.
Oplossing: Gebruik UUID v7 als je tijdgeordende identifiers nodig hebt. Gebruik UUID v4 voor tokens en correlatie-ID's waarbij sorteervolgorde niet relevant is.
// Bad: using v4 as a sortable primary key
const rows = [
{ id: crypto.randomUUID(), created: "2026-03-27" },
{ id: crypto.randomUUID(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// Sort order is random β NOT by creation dateimport { v7 as uuidv7 } from 'uuid';
// Good: v7 sorts by creation time
const rows = [
{ id: uuidv7(), created: "2026-03-27" },
{ id: uuidv7(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// Sort order matches creation timecrypto.randomUUID() vs uuid vs nanoid β Snelle vergelijking
Voor de meeste JavaScript-projecten: gebruik crypto.randomUUID() als je alleen UUID v4 nodig hebt en je runtime recent genoeg is. Gebruik het uuid pakket als je ondersteuning voor v5 (deterministisch) of v7 (tijdgeordend) nodig hebt. Gebruik nanoid als een korte, URL-veilige ID praktischer is dan een 36-tekens UUID β maar onthoud dat nanoid-uitvoer niet UUID-conform is en validatie mislukt op elk systeem dat RFC 4122- formaat verwacht.
Voor een no-code alternatief, probeer de UUID v4 Generator om direct identifiers in de browser te maken. Om een bestaande UUID te inspecteren, plak hem in de UUID Decoder om de versie, variant en eventuele ingebedde timestampgegevens te bekijken.
Veelgestelde vragen
Hoe genereer ik een UUID v4 in JavaScript?
Roep crypto.randomUUID() aan in elke moderne browser (Chrome 92+, Firefox 95+, Safari 15.4+) of Node.js 19+. Het geeft een kleine-letters string terug zoals "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f". In browsers is geen import nodig omdat crypto een ingebouwde global is; in Node.js kun je ook import { randomUUID } from "node:crypto" gebruiken om het module expliciet te maken. Voor runtimes ouder dan Node.js 19 kun je crypto.randomUUID() nog steeds via de global aanroepen β het was experimenteel beschikbaar vanaf Node.js 14.17.0. Als je een no-code-optie wilt, genereert de UUID v4 Generator op /en/uuid/v4 conforme identifiers met één klik.
const sessionId = crypto.randomUUID(); console.log(sessionId); // "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
Is crypto.randomUUID() cryptografisch veilig?
Ja. crypto.randomUUID() gebruikt dezelfde CSPRNG (cryptografisch veilige pseudowillekeurige getallengenerator) als crypto.getRandomValues(). De 122 willekeurige bits in een UUID v4 maken de kans op botsingen verwaarloosbaar voor alle praktische doeleinden β je zou ruwweg 2,71 triljard UUID's moeten genereren voordat je een kans van 50% op een enkele botsing bereikt. De entropie komt van de willekeurige bron van het besturingssysteem (/dev/urandom op Linux, BCryptGenRandom op Windows), niet van Math.random(), wat expliciet niet cryptografisch veilig is. Dit betekent dat UUID v4-waarden veilig zijn voor sessietokens, CSRF-tokens en andere beveiligingsgevoelige identifiers waar voorspelbaarheid vermeden moet worden. Gebruik nooit Math.random()-gebaseerde UUID-generators in beveiligingscontexten.
Kan ik UUID v4 gebruiken als primaire databasesleutel?
Dat kan, maar er is een merkbare prestatieafweging. UUID v4 is volledig willekeurig, waardoor B-tree-indexen slecht fragmenteren doordat elke nieuwe rij op een willekeurige positie in de index wordt ingevoegd in plaats van aan het einde. Op schrijf-intensieve tabellen veroorzaakt dit overmatige paginasplitsingen en cache-missers, wat INSERT- en bereikzoekprestaties verslechtert. Als je database dit ondersteunt (PostgreSQL, MySQL 8.0+, SQL Server), is UUID v7 (tijdgeordend) een betere primaire sleutel omdat nieuwe rijen altijd aan het einde van de index worden toegevoegd. UUID v4 blijft de juiste keuze voor sessietokens, OAuth-statusparameters, idempotentiesleutels, correlatie-ID's en elk veld waarbij het verbergen van de aanmaaktijd wenselijk is.
// UUID v4 β willekeurig, niet sorteerbaar
const correlationId = crypto.randomUUID();
// UUID v7 β tijdgeordend, beter voor DB-primaire sleutels
import { v7 as uuidv7 } from 'uuid';
const rowId = uuidv7();Wat is het verschil tussen UUID v4 en UUID v7?
UUID v4 vult 122 bits met willekeurige gegevens β elk segment is effectief ruis. UUID v7 (RFC 9562, gepubliceerd in 2024) codeert een 48-bit Unix-millisecondentimestamp in het eerste segment, 12 bits submillisecondenprecisie in het tweede segment, en willekeurige bits in de rest. Beide zijn 128 bits totaal en gebruiken hetzelfde 36-tekens koppeltekensformaat, waardoor ze uitwisselbaar zijn op het opslaglaagniveau. UUID v7 is lexicografisch sorteerbaar op aanmaaktijd, wat B-tree-indexen compact houdt en bereikzoekopdrachten op tijdvensters efficiΓ«nt maakt. Kies UUID v4 wanneer de ID niet mag onthullen wanneer hij is aangemaakt β bijvoorbeeld voor publiekgerichte tokens waarbij timinginformatie misbruikt kan worden β en UUID v7 voor databaseprimaire sleutels, auditlogs en eventstreams waarbij chronologische volgorde belangrijk is.
Hoe valideer ik een UUID v4-string in JavaScript?
Test tegen de regex /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i. De letterlijke "4" op positie 15 (0-geΓ―ndexeerd) bevestigt de versienibble; het teken op positie 20 β een van 8, 9, a of b β codeert de RFC 4122-variantbits. Deze regex wijst UUID v1, v7 en elke misvormde string correct af. De i-vlag maakt het hoofdletterongevoelig, zodat hoofdletters hexadecimale cijfers van andere systemen de validatie doorstaan zonder normalisatie. Als je alleen wilt weten of een string een geldige UUID is (ongeacht de versie), gebruik dan het soepelere patroon /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_V4_RE.test("550e8400-e29b-41d4-a716-446655440000"); // true
UUID_V4_RE.test("550e8400-e29b-11d4-a716-446655440000"); // false (v1)
UUID_V4_RE.test("not-a-uuid"); // falseHoe genereer ik een korte unieke ID in JavaScript?
Verwijder koppeltekens uit een UUID v4 om een 32-tekens hexadecimale string te krijgen: crypto.randomUUID().replaceAll("-", ""). Voor iets nog korter gebruik je nanoid, dat standaard een 21-tekens URL-veilige ID produceert (AβZ, aβz, 0β9, _ en -) met vergelijkbare botsingsbestendigheid als een volledige UUID. De afweging is eenvoudig: kortere ID's hebben een hogere botsingskans, maar nanoid met 21 tekens biedt nog steeds 126 bits entropie, wat meer dan voldoende is voor vrijwel elke toepassing in de praktijk. Voor URL-slugs en QR-codegegevens kun je terugaan tot 10β12 tekens met nanoid voordat de botsingskans een probleem wordt bij typische generatiesnelheden. Vermijd Base64-codering van een ruwe UUID en afkapping β afkapping vernietigt de statistische onafhankelijkheid van de bits en maakt botsingen moeilijker te redeneren.
// 32-tekens hexadecimale string van UUID v4
const hexId = crypto.randomUUID().replaceAll('-', '');
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"
// 21-tekens URL-veilige ID via nanoid
import { nanoid } from 'nanoid';
const shortId = nanoid();
// "V1StGXR8_Z5jdHi6B-myT"Gerelateerde tools
Sophie is a full-stack developer focused on TypeScript across the entire stack β from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.