UUID stands for Universally Unique Identifier — a 128-bit value formatted as 32 hex digits in five groups:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
^M = version, ^N = variant
Example: f47ac10b-58cc-4372-a567-0e02b2c3d479
The version digit (M) tells you how the UUID was generated. Version 4 is the most commonly used: entirely random, no private data, no coordination required.
UUID version quick reference
| Version | How generated | Use when |
|---|---|---|
| v1 | MAC address + timestamp | You need sortable IDs or audit trails |
| v3 | MD5 hash of name + namespace | Deterministic ID from a name (legacy) |
| v4 | Cryptographically random | Default choice — IDs that must be unique and unpredictable |
| v5 | SHA-1 hash of name + namespace | Deterministic ID from a name (prefer over v3) |
| v7 | Unix timestamp + random bits | Sortable like v1, random like v4 — modern databases |
For most use cases — database primary keys, session tokens, file names, request IDs — v4 is the right choice. Use v7 if you need time-ordered IDs (better index locality in B-tree databases).
JavaScript
Browser (modern)
crypto.randomUUID() is built into every modern browser and Node.js 14.17+:
// Browser and Node.js 14.17+
const id = crypto.randomUUID();
console.log(id); // "110e8400-e29b-41d4-a716-446655440000"
That's it. No imports, no packages. It uses the OS CSPRNG under the hood.
Node.js (older versions / more control)
The uuid npm package supports all versions and works in both environments:
npm install uuid
import { v4 as uuidv4, v1 as uuidv1, v5 as uuidv5 } from 'uuid';
// v4 — random
const id = uuidv4();
// v1 — time-based (contains MAC address, use carefully)
const timeId = uuidv1();
// v5 — deterministic from a name
const MY_NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; // URL namespace
const nameId = uuidv5('https://example.com', MY_NAMESPACE);
// same input always → same UUID
Bulk generation
const ids = Array.from({ length: 10 }, () => crypto.randomUUID());
Python
The uuid module is in the standard library — no installation needed:
import uuid
# v4 — random (most common)
id_v4 = uuid.uuid4()
print(id_v4) # UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')
print(str(id_v4)) # 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
print(id_v4.hex) # 'f47ac10b58cc4372a5670e02b2c3d479' (no hyphens)
# v1 — time-based
id_v1 = uuid.uuid1()
# v5 — deterministic from namespace + name
id_v5 = uuid.uuid5(uuid.NAMESPACE_URL, 'https://example.com')
# uuid.NAMESPACE_URL, NAMESPACE_DNS, NAMESPACE_OID, NAMESPACE_X500
# Convert string back to UUID object
parsed = uuid.UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')
print(parsed.version) # 4
Bulk generation
import uuid
ids = [str(uuid.uuid4()) for _ in range(10)]
Go
The standard library has no UUID package, but google/uuid is the canonical choice:
go get github.com/google/uuid
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
// v4 — random
id, err := uuid.NewRandom()
if err != nil {
panic(err) // only fails if /dev/urandom is unavailable
}
fmt.Println(id) // f47ac10b-58cc-4372-a567-0e02b2c3d479
fmt.Println(id.String()) // same
// v1 — time-based
idV1, _ := uuid.NewUUID()
// v7 — time-ordered + random (added in google/uuid v1.6)
idV7, _ := uuid.NewV7()
fmt.Println(idV7) // sortable: recent IDs cluster together in DB index
// Parse a UUID string
parsed, err := uuid.Parse("f47ac10b-58cc-4372-a567-0e02b2c3d479")
if err != nil {
panic(err)
}
fmt.Println(parsed.Version()) // 4
}
Without a library (v4 only)
If you cannot add dependencies, you can build a v4 UUID manually:
import (
"crypto/rand"
"fmt"
)
func newUUID() string {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
// Set version 4 and variant bits
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}
PHP
Built-in (PHP 8.3+)
PHP 8.3 added Str::uuid() in Laravel, but the language itself still has no native UUID function. For plain PHP, use the ramsey/uuid package:
composer require ramsey/uuid
<?php
use Ramsey\Uuid\Uuid;
// v4 — random
$id = Uuid::uuid4()->toString();
echo $id; // f47ac10b-58cc-4372-a567-0e02b2c3d479
// v1 — time-based
$idV1 = Uuid::uuid1()->toString();
// v5 — deterministic
$idV5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'https://example.com')->toString();
// Parse and inspect
$parsed = Uuid::fromString('f47ac10b-58cc-4372-a567-0e02b2c3d479');
echo $parsed->getVersion(); // 4
Without Composer (v4 only)
function generateUuidV4(): string {
$bytes = random_bytes(16);
// Set version 4 and variant bits
$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x40);
$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}
echo generateUuidV4(); // f47ac10b-58cc-4372-a567-0e02b2c3d479
Quick reference
| Language | v4 (random) | v5 (named) | v7 (sortable) |
|---|---|---|---|
| JavaScript | crypto.randomUUID() |
uuid package v5() |
uuid package v7() |
| Python | uuid.uuid4() |
uuid.uuid5(NS, name) |
third-party uuid6 |
| Go | uuid.NewRandom() |
uuid.NewSHA1() |
uuid.NewV7() |
| PHP | Uuid::uuid4() |
Uuid::uuid5() |
Uuid::uuid7() |
| CLI | uuidgen (Linux/macOS) |
— | — |
| Online | Toolko UUID Generator | — | — |
6 common mistakes
1. Using Math.random() to build a UUIDMath.random() is not cryptographically secure. IDs generated this way can be predicted. Always use crypto.randomUUID() or a library that uses the CSPRNG.
2. Storing as VARCHAR(255) instead of CHAR(36)
A UUID is always exactly 36 characters (32 hex + 4 hyphens). Use CHAR(36) or, better, a native UUID column type (PostgreSQL, MySQL 8+). If storage size matters, store as BINARY(16) and convert at the application layer.
3. Using v1 when you need privacy
UUID v1 embeds your MAC address and the current timestamp. Anyone who sees the UUID can deduce your network interface and the exact time it was generated. Use v4 for any user-facing or public IDs.
4. Assuming UUID means "unique forever"
UUID v4 has 122 random bits (~5.3 × 10³⁶ possible values). Collision probability is negligible in practice, but "universally unique" is a statistical guarantee, not a mathematical one. For high-volume systems generating billions of IDs per second, v7 with a monotonic counter offers stronger guarantees.
5. Reinventing UUID when you need something sortable
If you need time-ordered IDs for database performance, use UUID v7 or a library like ULID instead of storing a timestamp column alongside a v4 UUID. UUID v7 is sortable by creation time and compatible with existing UUID fields.
6. Forgetting to validate on input
When accepting a UUID from user input or an API, always validate the format before querying the database. An invalid UUID passed to a WHERE id = ? query causes a type error in strict databases and a full table scan in lenient ones.
// Validation regex (RFC 4122)
const isUUID = (s) =>
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(s);
FAQ
What's the difference between UUID and GUID?
Nothing meaningful. GUID (Globally Unique Identifier) is Microsoft's name for the same standard. They are interchangeable in format and generation.
Can two UUID v4s ever be the same?
Theoretically yes, practically no. Generating a duplicate v4 UUID is less likely than winning the lottery 3 times in a row. Worry about this only if you're generating more than ~10¹⁵ UUIDs.
Should I use UUID as a primary key?
It depends. UUIDs are great for distributed systems (no coordination needed) and security (IDs not guessable). The downside is index fragmentation in B-tree databases when using random v4. Use v7 or ULID if you need both UUIDs and good write performance.
UUID v4 or ULID?
ULID is a newer alternative: 26-character base32, URL-safe, sortable. Use ULID if you want sortability and don't need UUID compatibility. Use UUID v7 if you need standard UUID format and sortability.
How do I generate a UUID without a library in the browser?crypto.randomUUID() is natively available in all modern browsers (Chrome 92+, Firefox 95+, Safari 15.4+). For older browsers, polyfill using crypto.getRandomValues() and format manually.
Is a UUID the same as a hash?
No. A hash (MD5, SHA-256) maps input data to a fixed-size output deterministically. UUID v4 is purely random with no input. UUID v5 is deterministic (like a hash) but uses SHA-1 and outputs in UUID format.