The uuid module generates universally unique identifiers—128-bit values that are practically guaranteed to be unique across time and space.

The Four UUID Types

import uuid
 
# UUID1: based on host MAC + timestamp
u1 = uuid.uuid1()
# Reveals when/where it was created
 
# UUID3: MD5 hash of namespace + name
u3 = uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
# Deterministic: same input = same UUID
 
# UUID4: random
u4 = uuid.uuid4()
# Most common choice
 
# UUID5: SHA-1 hash of namespace + name
u5 = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
# Like UUID3 but with SHA-1

UUID4: The Default Choice

For most applications, use uuid4():

import uuid
 
# Generate random UUID
user_id = uuid.uuid4()
print(user_id)
# 550e8400-e29b-41d4-a716-446655440000
 
# As string
print(str(user_id))
 
# As 32-char hex (no dashes)
print(user_id.hex)
# 550e8400e29b41d4a716446655440000
 
# As bytes
print(user_id.bytes)
# b'U\x0e\x84\x00\xe2\x9bA\xd4\xa7\x16DfUD\x00\x00'
 
# As integer
print(user_id.int)

UUID5: Deterministic IDs

When you need the same UUID for the same input:

import uuid
 
# Built-in namespaces
ns_dns = uuid.NAMESPACE_DNS    # For domain names
ns_url = uuid.NAMESPACE_URL    # For URLs
ns_oid = uuid.NAMESPACE_OID    # For ISO OIDs
ns_x500 = uuid.NAMESPACE_X500  # For X.500 DNs
 
# Same input always gives same UUID
id1 = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
id2 = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
assert id1 == id2
 
# Different namespace or name = different UUID
id3 = uuid.uuid5(uuid.NAMESPACE_URL, 'example.com')
assert id1 != id3

Use cases:

  • Idempotent imports (same source data = same ID)
  • Derived IDs (user ID + "profile" = profile ID)
  • Content addressing

UUID1: Time-Based

Contains timestamp and MAC address:

import uuid
 
u = uuid.uuid1()
 
# Extract timestamp (100-ns intervals since Oct 1582)
print(u.time)
 
# Extract node (usually MAC address)
print(hex(u.node))

Privacy concern: Reveals creation time and host identity.

Use when you need:

  • Sortable IDs (rough time ordering)
  • Audit trail (know when/where created)

Parsing UUIDs

import uuid
 
# From string
u = uuid.UUID('550e8400-e29b-41d4-a716-446655440000')
 
# From hex (no dashes)
u = uuid.UUID('550e8400e29b41d4a716446655440000')
 
# From bytes
u = uuid.UUID(bytes=b'U\x0e\x84\x00\xe2\x9bA\xd4\xa7\x16DfUD\x00\x00')
 
# From int
u = uuid.UUID(int=113059749145936325402354257176981405696)

UUID Properties

u = uuid.uuid4()
 
u.hex        # 32-char hex string
u.bytes      # 16 bytes
u.int        # 128-bit integer
u.urn        # 'urn:uuid:...'
u.version    # 4 for uuid4
u.variant    # uuid.RFC_4122

Common Patterns

Database Primary Keys

from dataclasses import dataclass, field
import uuid
 
@dataclass
class User:
    id: uuid.UUID = field(default_factory=uuid.uuid4)
    name: str = ""
    email: str = ""
 
user = User(name="Alice", email="alice@example.com")
print(user.id)  # Auto-generated UUID

URL-Safe Short IDs

import uuid
import base64
 
def short_uuid() -> str:
    """Generate a URL-safe 22-char ID."""
    u = uuid.uuid4()
    return base64.urlsafe_b64encode(u.bytes).rstrip(b'=').decode()
 
print(short_uuid())  # 'VQ6EAOKbQdSnFkRmVUQAAA'

Derived IDs

import uuid
 
def derived_id(parent_id: uuid.UUID, suffix: str) -> uuid.UUID:
    """Generate deterministic child ID."""
    return uuid.uuid5(parent_id, suffix)
 
user_id = uuid.uuid4()
profile_id = derived_id(user_id, 'profile')
settings_id = derived_id(user_id, 'settings')

When to Use What

TypeWhen to Use
UUID4Default choice. Random, no information leak.
UUID5Deterministic mapping from input to ID.
UUID1Need timestamp/sorting, accept privacy tradeoff.
UUID3Like UUID5 but legacy (MD5).

Comparison with Alternatives

FormatLengthSortableInfo Leak
UUID436 charsNoNone
UUID136 charsPartialTime + MAC
ULID26 charsYesTime
nanoid21 charsNoNone
Auto-incrementVariableYesCount

UUIDs are verbose but universally understood and supported by every database.

Quick Reference

import uuid
 
# Generate
uuid.uuid4()              # Random (most common)
uuid.uuid5(ns, name)      # Deterministic from input
uuid.uuid1()              # Time + MAC based
 
# Parse
uuid.UUID('string')       # From string
uuid.UUID(hex='...')      # From hex
uuid.UUID(bytes=b'...')   # From bytes
 
# Properties
u.hex                     # Without dashes
u.bytes                   # Raw bytes
u.int                     # Integer
str(u)                    # With dashes

Start with uuid4(). Reach for uuid5() when you need determinism.

React to this post: