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:
| Version | Based On | Privacy Safe | Use Case |
|---|---|---|---|
uuid1() | Timestamp + MAC address | ❌ | Time-ordered IDs, logging |
uuid3() | MD5 hash of namespace + name | ✅ | Deterministic IDs from names |
uuid4() | Random numbers | ✅ | General-purpose unique IDs |
uuid5() | SHA-1 hash of namespace + name | ✅ | Deterministic IDs (more secure than uuid3) |
Method 1: Using uuid4() (Recommended for Most Cases)
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
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.
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
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
| Requirement | Recommended Version |
|---|---|
| General-purpose unique ID | uuid4() |
| Time-ordered ID (non-sensitive) | uuid1() |
| Deterministic ID from a name | uuid5() (or uuid3()) |
| Security token / API key | Use secrets module instead |
| Short unique ID | uuid4().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
secretsmodule for cryptographic purposes. - Access different representations with
.hex,.int,.bytes, orstr()depending on your storage or transmission needs.