Skip to main content

How to Generate Random IDs Using UUID in Python

Generating unique identifiers is a fundamental requirement in software development, from database primary keys and session tokens to distributed system coordination and file naming. Python's built-in uuid module provides a reliable, standardized way to create Universally Unique Identifiers (UUIDs) as defined by RFC 4122, ensuring that each ID is virtually guaranteed to be unique across time and space.

In this guide, you'll learn how to generate random IDs using different UUID versions, understand their internal structure, and choose the right approach based on your uniqueness, privacy, and security requirements.

What Is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit value formatted as a 32-character hexadecimal string with hyphens:

fbd204a7-318e-4dd3-86e0-e6d524fc3f98

The probability of generating two identical UUIDs is astronomically low: roughly 1 in 5.3 × 10³⁶. This makes them safe to use as unique identifiers without any central coordination.

Python's uuid module supports several UUID versions:

VersionBased OnPrivacy SafeUse Case
uuid1()Timestamp + MAC addressTime-ordered IDs, logging
uuid3()MD5 hash of namespace + nameDeterministic IDs from names
uuid4()Random numbersGeneral-purpose unique IDs
uuid5()SHA-1 hash of namespace + nameDeterministic IDs (more secure than uuid3)

uuid4() generates a UUID using 122 bits of randomness, with no dependence on hardware or timestamps. This is the most commonly used version and the best default choice:

import uuid

uid = uuid.uuid4()
print("Random UUID:", uid)
print("As string: ", str(uid))

Output:

Random UUID: 613a4e90-8659-4c22-a22a-2ce344316154
As string: 613a4e90-8659-4c22-a22a-2ce344316154

Why uuid4() Is Usually the Best Choice

  • No privacy leaks: Doesn't expose your MAC address or system time.
  • No coordination needed: Can be generated independently on any machine.
  • Extremely low collision probability: Safe for databases, APIs, and distributed systems.
  • Simple: Just call uuid.uuid4(): no configuration required.

Common Formats

import uuid

uid = uuid.uuid4()

print("Standard: ", uid) # With hyphens
print("Hex: ", uid.hex) # 32 chars, no hyphens
print("Integer: ", uid.int) # 128-bit integer
print("Bytes: ", uid.bytes) # 16-byte string
print("URN: ", uid.urn) # URN format

Output:

Standard:   622cea47-3525-4dd7-a623-4550b9391fd5
Hex: 622cea4735254dd7a6234550b9391fd5
Integer: 130497556374191884339973281723981570005
Bytes: b'b,\xeaG5%M\xd7\xa6#EP\xb99\x1f\xd5'
URN: urn:uuid:622cea47-3525-4dd7-a623-4550b9391fd5

Generating Multiple UUIDs

import uuid

# Generate 5 unique IDs
for i in range(5):
print(f"ID {i + 1}: {uuid.uuid4()}")

Output:

ID 1: 4566732f-8f20-4092-963c-cfc9e6d31067
ID 2: 4363d75e-51e7-484c-a1de-cb1ba8647ea8
ID 3: efa93ee9-f0a9-4b54-aeb1-1df5a12fa6ee
ID 4: 5739980c-b2a1-44d1-b7d4-edb413a877cb
ID 5: cf516b69-de55-4515-ba55-973af60bc387

Method 2: Using uuid1() (Time-Based)

uuid1() generates a UUID using the current timestamp and the machine's MAC address. This guarantees uniqueness and provides time-ordering, but exposes hardware information:

import uuid

uid = uuid.uuid1()
print("UUID1:", uid)

Output:

UUID1: ecc72432-09f3-11f1-ac2f-7aedd2986efe

Exploring UUID1 Components

import uuid

uid = uuid.uuid1()

# Representations
print("Byte repr:", repr(uid.bytes))
print("Integer: ", uid.int)
print("Hex: ", uid.hex)

# Metadata
print("\nVersion:", uid.version)
print("Variant:", uid.variant)

# Fields
print("\nFields:", uid.fields)
print("Time Low: ", uid.fields[0])
print("Time Mid: ", uid.fields[1])
print("Time Hi: ", uid.fields[2])
print("Clock Seq Hi: ", uid.fields[3])
print("Clock Seq Low:", uid.fields[4])
print("Node (MAC): ", uid.fields[5])

Output:

Byte repr: b'\xf2I$\x14\t\xf3\x11\xf1\x92 z\xed\xd2\x98n\xfe'
Integer: 322052944405010884204009590938400222974
Hex: f249241409f311f192207aedd2986efe

Version: 1
Variant: specified in RFC 4122

Fields: (4064879636, 2547, 4593, 146, 32, 135161859043070)
Time Low: 4064879636
Time Mid: 2547
Time Hi: 4593
Clock Seq Hi: 146
Clock Seq Low: 32
Node (MAC): 135161859043070
Privacy Concern with uuid1()

uuid1() embeds your machine's MAC address in the last 48 bits of the UUID. This means anyone who sees the UUID can potentially identify the machine that generated it. Avoid uuid1() in applications where privacy matters; use uuid4() instead.

Method 3: Using uuid3() and uuid5() (Name-Based, Deterministic)

These versions generate deterministic UUIDs from a namespace and a name. The same inputs always produce the same UUID:

import uuid

# uuid3 uses MD5 hashing
uid3 = uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
print("UUID3:", uid3)

# uuid5 uses SHA-1 hashing (preferred over uuid3)
uid5 = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
print("UUID5:", uid5)

# Same input always produces the same output
uid5_again = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
print("Same? ", uid5 == uid5_again)

Output:

UUID3: 9073926b-929f-31c2-abc9-fad77ae3e8eb
UUID5: cfbff0d1-9375-5685-968c-48ce8b15ae17
Same? True

Available namespaces include NAMESPACE_DNS, NAMESPACE_URL, NAMESPACE_OID, and NAMESPACE_X500.

When to use name-based UUIDs

Use uuid3() or uuid5() when you need the same ID every time for the same input: for example, generating consistent IDs for URLs, usernames, or resource names. Prefer uuid5() over uuid3() because SHA-1 is more collision-resistant than MD5.

Practical Examples

Using UUIDs as Database Keys

import uuid

class User:
def __init__(self, name, email):
self.id = str(uuid.uuid4())
self.name = name
self.email = email

user = User("Alice", "alice@example.com")
print(f"User ID: {user.id}")
print(f"Name: {user.name}")

Output:

User ID: 85824d32-8776-4b8b-9558-72f55eef1d3c
Name: Alice

Generating Short IDs from UUIDs

Full UUIDs are 36 characters long. If you need shorter IDs, you can truncate or encode them:

import uuid

uid = uuid.uuid4()

# Use first 8 characters of the hex representation
short_id = uid.hex[:8]
print(f"Full UUID: {uid}")
print(f"Short ID: {short_id}")

Output:

Full UUID: d525e374-7b31-43ab-b13a-b30dbea591c0
Short ID: d525e374
caution

Truncating UUIDs significantly increases collision probability. An 8-character hex string has only 4 billion possible values. For small-scale applications this may be acceptable, but for large systems, use the full UUID.

Generating Unique Filenames

import uuid

def generate_filename(extension='txt'):
return f"{uuid.uuid4().hex[:12]}.{extension}"

print(generate_filename('txt'))
print(generate_filename('png'))
print(generate_filename('csv'))

Output:

bd1d2f0248b4.txt
6d5239bea811.png
4d133acdc7e8.csv

Common Mistake: Using UUIDs for Security Tokens

UUIDs are designed for uniqueness, not security. uuid4() uses Python's random module, which may not be cryptographically secure in all implementations:

import uuid

# ❌ Not suitable for authentication tokens or secrets
token = str(uuid.uuid4())

Use the secrets module instead for security-sensitive identifiers:

import secrets

# ✅ Cryptographically secure token
token = secrets.token_hex(16)
print("Secure token:", token)

# ✅ URL-safe token
url_token = secrets.token_urlsafe(16)
print("URL-safe token:", url_token)

Output:

Secure token: 9f8958cd1a5458e87e3d11ee6350f74d
URL-safe token: RXr18jE1GW7yyHZ_yiio4g

Choosing the Right UUID Version

RequirementRecommended Version
General-purpose unique IDuuid4()
Time-ordered ID (non-sensitive)uuid1()
Deterministic ID from a nameuuid5() (or uuid3())
Security token / API keyUse secrets module instead
Short unique IDuuid4().hex[:N] (with collision risk)

Summary

Python's uuid module provides a simple, reliable way to generate unique identifiers:

  • Use uuid4() as your default: it's random, privacy-safe, and requires no configuration.
  • Use uuid1() when you need time-ordering, but be aware it exposes your MAC address.
  • Use uuid5() when you need deterministic IDs that are always the same for the same input.
  • Never use UUIDs as security tokens: use the secrets module for cryptographic purposes.
  • Access different representations with .hex, .int, .bytes, or str() depending on your storage or transmission needs.