Python UUID Versions 1, 4, and 5 Explained
Python's built-in uuid module provides tools to generate
Universally Unique Identifiers based on established internet standards.
This article explores RFC 4122—the formal specification that defines and
differentiates UUID versions—and breaks down how version 1, version 4,
and version 5 differ in Python in terms of source data, determinism, and
common use cases.
The Governing Standard: RFC 4122
The standard that establishes and differentiates UUID versions 1, 4, and 5 is RFC 4122 ("A Universally Unique IDentifier (UUID) URN Namespace"), updated in modern contexts by RFC 9562.
RFC 4122 reserves specific bits within the 128-bit integer to identify the UUID's variant (usually variant 1 for standard UUIDs) and its version (occupying bits 48 through 51). The version sub-field informs the system which underlying algorithm generated the identifier.
UUID Version 1: Host ID and Timestamp
In Python, uuid.uuid1() produces a 128-bit identifier
derived from:
- The host computer's MAC address (48 bits).
- The current UTC timestamp measured in 100-nanosecond intervals since October 15, 1582 (60 bits).
- A clock sequence counter to handle clock resets or system time adjustments (14 bits).
import uuid
v1 = uuid.uuid1()
print(v1)Key Characteristics:
- Uniqueness: Guarantees temporal and spatial uniqueness across networks without a centralized authority.
- Drawbacks: Exposes the generating machine's network card MAC address and exact creation timestamp, posing potential security and privacy risks.
UUID Version 4: Cryptographic Randomness
Python's uuid.uuid4() relies entirely on pseudo-random
numbers. Out of 128 bits, 6 bits are fixed (variant and version),
leaving 122 bits of pure entropy. Python sources this entropy directly
from os.urandom(), making it cryptographically strong.
import uuid
v4 = uuid.uuid4()
print(v4)Key Characteristics:
- Uniqueness: Purely statistical. The probability of generating a duplicate UUIDv4 is roughly 1 in \(2^{122}\), an infinitesimally small collision risk.
- Privacy: Contains no identifying system information or timestamps.
- Usage: The industry standard for primary keys, session tokens, and request tracking.
UUID Version 5: Namespaces and SHA-1 Hashing
Python's uuid.uuid5() generates deterministic UUIDs
using a designated namespace UUID and an arbitrary string name. It
combines these inputs and generates a cryptographic hash using SHA-1,
truncating the result to fit the 128-bit UUID structure.
import uuid
# Uses a predefined namespace (e.g., DNS, URL, OID, X500)
namespace = uuid.NAMESPACE_DNS
name = "example.com"
v5 = uuid.uuid5(namespace, name)
print(v5)Key Characteristics:
- Determinism: Passing the exact same namespace and string will always produce the identical UUID across any platform or time.
- Hashing Algorithm: Uses SHA-1 (unlike UUID Version 3, which uses MD5).
- Usage: Ideal for generating stable IDs for external entities (such as URLs, hostnames, or usernames) without maintaining a centralized lookup database.
Comparison Summary
| Version | Function | Algorithm / Source | Deterministic? | Privacy Risk |
|---|---|---|---|---|
| UUIDv1 | uuid.uuid1() |
MAC Address + Gregorian Timestamp | No | High (exposes MAC & time) |
| UUIDv4 | uuid.uuid4() |
Cryptographic Random Bits
(os.urandom) |
No | None |
| UUIDv5 | uuid.uuid5() |
SHA-1 Hash of Namespace + Name | Yes | None |