Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Generating UUIDs in Python

On this page
  1. The standard library
  2. v7 (Python 3.13+)
  3. Parsing UUIDs from strings
  4. Validation
  5. Cryptographic randomness
  6. Database integration
    1. PostgreSQL with psycopg
    2. SQLAlchemy
  7. Django
  8. Performance
  9. Common pitfalls
  10. Cheat sheet
  11. Try the tools

Python has had a built-in uuid module since 2.5 (~2006). It covers v1, v3, v4, and v5 out of the box. v7 arrived in the standard library in Python 3.13 (October 2024); for earlier interpreters you need a third-party package.

The standard library

import uuid

uuid.uuid4()                                    # random — the default
# UUID('12fbc73a-9e9d-44b1-9e6d-1d3e7c8a0f31')

uuid.uuid1()                                    # time + node
uuid.uuid3(uuid.NAMESPACE_DNS, "example.com")   # MD5 of namespace + name
uuid.uuid5(uuid.NAMESPACE_URL, "https://x.io")  # SHA-1 of namespace + name

uuid.UUID is the type. It’s hashable and comparable, and it serializes cleanly:

u = uuid.uuid4()
str(u)        # "12fbc73a-9e9d-44b1-9e6d-1d3e7c8a0f31"
u.hex         # "12fbc73a9e9d44b19e6d1d3e7c8a0f31"
u.bytes       # b'\x12\xfb\xc7:\x9e\x9dD\xb1\x9emN>...'
u.int         # 25190934987130523... (single 128-bit int)
u.version     # 4
u.variant     # 'specified in RFC 4122'

v7 (Python 3.13+)

# Python 3.13 and newer
import uuid
uuid.uuid7()
# UUID('01928a47-3b30-7c5e-9d1a-f0b8c4a7e923')

For older Pythons, install uuid-utils — a Rust-backed library that adds v6, v7, and v8:

# pip install uuid-utils
import uuid_utils
uuid_utils.uuid7()
# UUID('01928a47-3b30-7c5e-9d1a-f0b8c4a7e923')

uuid_utils.UUID is a drop-in for the standard library type, so str(), .hex, .bytes, etc. all work the same way.

Parsing UUIDs from strings

u = uuid.UUID("12fbc73a-9e9d-44b1-9e6d-1d3e7c8a0f31")            # canonical
u = uuid.UUID("12fbc73a9e9d44b19e6d1d3e7c8a0f31")                # no hyphens
u = uuid.UUID("{12fbc73a-9e9d-44b1-9e6d-1d3e7c8a0f31}")          # braces
u = uuid.UUID(bytes=b'\x12\xfb...')                              # 16 raw bytes
u = uuid.UUID(int=25190934987130523...)                          # int

The constructor accepts every form. Invalid strings raise ValueError — use a try/except for user-supplied input.

Validation

The Pythonic way is to let the constructor do it:

def is_uuid(s: str) -> bool:
    try:
        uuid.UUID(s)
        return True
    except ValueError:
        return False

For stricter checks (e.g. require canonical hyphenated form):

def is_canonical_uuid(s: str) -> bool:
    try:
        return str(uuid.UUID(s)) == s.lower()
    except ValueError:
        return False

Cryptographic randomness

Python’s uuid.uuid4() uses os.urandom() under the hood, which is the platform’s CSPRNG (getrandom(2) on Linux, BCryptGenRandom on Windows). It’s safe to use as a session token or password reset URL component on any modern OS — though see collision probability for limits.

Database integration

PostgreSQL with psycopg

import psycopg
import uuid

with psycopg.connect("postgresql://...") as conn:
    cur = conn.cursor()
    cur.execute(
        "INSERT INTO users (id, email) VALUES (%s, %s)",
        (uuid.uuid4(), "alice@example.com"),
    )

psycopg v3 maps Python uuid.UUID ↔ PostgreSQL uuid automatically. Older psycopg2 needs register_uuid().

SQLAlchemy

from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import UUID
import uuid

class User(Base):
    __tablename__ = "users"
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)

For a v7 default, swap in default=uuid.uuid7 (3.13+) or uuid_utils.uuid7.

Django

# models.py
from django.db import models
import uuid

class Order(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

For Django REST Framework, UUIDField works in serializers without configuration.

Performance

The standard library’s uuid4() is fine for most apps — typical throughput is 200,000–500,000 UUIDs/second on a modern machine. If you need more, uuid_utils (Rust) is ~5× faster. For batch generation in a tight loop, generate from secrets.token_bytes(16) and set the version/variant bits manually.

Common pitfalls

Cheat sheet

GoalCode
Random UUIDuuid.uuid4()
Time-ordered (DB key)uuid.uuid7() (3.13+) or uuid_utils.uuid7()
Deterministic from nameuuid.uuid5(ns, name)
Parseuuid.UUID(s)
Bytes for storageu.bytes
32-char hexu.hex
Validatetry uuid.UUID(s)

Try the tools