How to Check UUID Validity in Python
A UUID (Universally Unique Identifier) is a 128-bit label used to uniquely identify objects, records, or entities across distributed systems without requiring a central authority. UUIDs are represented as 32 hexadecimal digits displayed in five groups separated by hyphens, following the pattern 8-4-4-4-12, for example: 550e8400-e29b-41d4-a716-446655440000.
Validating UUIDs is essential when processing API requests, importing data, working with database keys, or handling user input. In this guide, you'll learn multiple ways to check UUID validity in Python, including using the built-in uuid module and regular expressions.
Understanding UUID Versions
Before validating UUIDs, it helps to understand the different versions, as each serves a distinct purpose:
| Version | Generation Method | Use Case |
|---|---|---|
| 1 | Timestamp + host MAC address | Time-ordered identifiers |
| 3 | MD5 hash of namespace + name | Deterministic, name-based |
| 4 | Randomly generated | General-purpose, most common |
| 5 | SHA-1 hash of namespace + name | Deterministic, name-based (more secure than v3) |
Version 4 UUIDs are the most widely used in modern applications because they are randomly generated and don't leak information about the host or timestamp.
Using the uuid Module (Recommended)
Python's built-in uuid module provides the most reliable way to validate UUIDs. The uuid.UUID() constructor attempts to parse a string into a UUID object. If the string is invalid, it raises a ValueError.
import uuid
def is_valid_uuid(uuid_string, version=None):
"""
Check if a string is a valid UUID.
Args:
uuid_string: The string to validate.
version: Optional UUID version (1, 3, 4, or 5) to validate against.
Returns:
True if valid, False otherwise.
"""
try:
uuid_obj = uuid.UUID(uuid_string)
except (ValueError, AttributeError):
return False
# If a specific version is required, check it
if version is not None:
return uuid_obj.version == version
return True
# Test with valid UUIDs
print(is_valid_uuid("550e8400-e29b-41d4-a716-446655440000"))
print(is_valid_uuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
# Test with invalid UUIDs
print(is_valid_uuid("not-a-uuid"))
print(is_valid_uuid("550e8400-e29b-41d4-a716-44665544000Z"))
# Test with version check
print(is_valid_uuid("550e8400-e29b-41d4-a716-446655440000", version=4))
Output:
True
True
False
False
True
How It Works
uuid.UUID(uuid_string)attempts to parse the input string.- If the string doesn't conform to UUID format, a
ValueErroris raised and caught. - If a specific
versionis provided, the function additionally verifies that the parsed UUID matches that version.
uuid.UUID() Is Lenient with FormattingThe uuid.UUID() constructor accepts UUIDs in multiple formats, with or without hyphens, with curly braces, and even with a urn:uuid: prefix:
import uuid
# All of these are accepted as valid
formats = [
"550e8400-e29b-41d4-a716-446655440000", # Standard
"550e8400e29b41d4a716446655440000", # No hyphens
"{550e8400-e29b-41d4-a716-446655440000}", # Curly braces
"urn:uuid:550e8400-e29b-41d4-a716-446655440000", # URN prefix
]
for fmt in formats:
try:
uuid.UUID(fmt)
print(f"✅ Valid: {fmt}")
except ValueError:
print(f"❌ Invalid: {fmt}")
Output:
✅ Valid: 550e8400-e29b-41d4-a716-446655440000
✅ Valid: 550e8400e29b41d4a716446655440000
✅ Valid: {550e8400-e29b-41d4-a716-446655440000}
✅ Valid: urn:uuid:550e8400-e29b-41d4-a716-446655440000
If you need to enforce the standard hyphenated format specifically, add an additional string comparison check (shown in the next section).
Enforcing the Standard Hyphenated Format
If your application requires UUIDs in the exact 8-4-4-4-12 hyphenated format, compare the normalized output of uuid.UUID() against the original input:
import uuid
def is_valid_uuid_strict(uuid_string, version=None):
"""Validate UUID and ensure it uses the standard hyphenated format."""
try:
uuid_obj = uuid.UUID(uuid_string)
except (ValueError, AttributeError):
return False
# Ensure the string matches the canonical format
if str(uuid_obj) != uuid_string.lower().strip():
return False
if version is not None:
return uuid_obj.version == version
return True
# Standard format: valid
print(is_valid_uuid_strict("550e8400-e29b-41d4-a716-446655440000"))
# No hyphens: rejected by strict check
print(is_valid_uuid_strict("550e8400e29b41d4a716446655440000"))
# Curly braces: rejected by strict check
print(is_valid_uuid_strict("{550e8400-e29b-41d4-a716-446655440000}"))
Output:
True
False
False
Using Regular Expressions
For lightweight validation without importing the uuid module, or when you need to extract UUIDs from text, regular expressions offer a fast alternative:
import re
UUID_PATTERN = re.compile(
r'^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$',
re.IGNORECASE
)
def is_valid_uuid_regex(uuid_string):
"""Validate UUID format using a regular expression."""
return bool(UUID_PATTERN.match(uuid_string))
print(is_valid_uuid_regex("550e8400-e29b-41d4-a716-446655440000")) # Valid
print(is_valid_uuid_regex("not-a-valid-uuid")) # Invalid
print(is_valid_uuid_regex("550e8400-e29b-41d4-a716-44665544000Z")) # Invalid (Z)
print(is_valid_uuid_regex("550e8400e29b41d4a716446655440000")) # Invalid (no hyphens)
Output:
True
False
False
False
Pattern breakdown:
| Segment | Meaning |
|---|---|
[0-9a-f]{8} | First group: 8 hex characters |
[0-9a-f]{4} | Second group: 4 hex characters |
[1-5][0-9a-f]{3} | Third group: version digit (1–5) + 3 hex characters |
[89ab][0-9a-f]{3} | Fourth group: variant digit (8, 9, a, or b) + 3 hex characters |
[0-9a-f]{12} | Fifth group: 12 hex characters |
The regex approach validates the format only, it checks structure, version digit, and variant digit. The uuid.UUID() approach is more thorough because it actually constructs a UUID object and validates the internal consistency.
Extracting UUIDs from Text
If you need to find and validate UUIDs embedded within larger text (such as log files or API responses), use re.findall():
import re
import uuid
def is_valid_uuid(uuid_string, version=None):
"""
Check if a string is a valid UUID.
Args:
uuid_string: The string to validate.
version: Optional UUID version (1, 3, 4, or 5) to validate against.
Returns:
True if valid, False otherwise.
"""
try:
uuid_obj = uuid.UUID(uuid_string)
except (ValueError, AttributeError):
return False
# If a specific version is required, check it
if version is not None:
return uuid_obj.version == version
return True
text = """
Request ID: 550e8400-e29b-41d4-a716-446655440000
Session: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
Invalid ref: not-a-uuid-value
Trace: 123e4567-e89b-12d3-a456-426614174000
"""
UUID_PATTERN = re.compile(
r'[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}',
re.IGNORECASE
)
found_uuids = UUID_PATTERN.findall(text)
for uid in found_uuids:
print(f"Found: {uid} (valid: {is_valid_uuid(uid)})")
Output:
Found: 550e8400-e29b-41d4-a716-446655440000 (valid: True)
Found: 6ba7b810-9dad-11d1-80b4-00c04fd430c8 (valid: True)
Found: 123e4567-e89b-12d3-a456-426614174000 (valid: True)
Validating UUID Version Specifically
When your application requires a specific UUID version, validate both the format and the version number:
import uuid
def validate_uuid_version(uuid_string, required_version):
"""Validate that a UUID string is valid and matches the required version."""
try:
uuid_obj = uuid.UUID(uuid_string)
except ValueError:
return False, "Invalid UUID format"
if uuid_obj.version != required_version:
return False, f"Expected version {required_version}, got version {uuid_obj.version}"
return True, f"Valid UUID v{required_version}"
test_cases = [
("550e8400-e29b-41d4-a716-446655440000", 4),
("6ba7b810-9dad-11d1-80b4-00c04fd430c8", 1),
("550e8400-e29b-41d4-a716-446655440000", 1), # Wrong version
]
for uid, version in test_cases:
is_valid, message = validate_uuid_version(uid, version)
status = "✅" if is_valid else "❌"
print(f"{status} {uid} (v{version}): {message}")
Output:
✅ 550e8400-e29b-41d4-a716-446655440000 (v4): Valid UUID v4
✅ 6ba7b810-9dad-11d1-80b4-00c04fd430c8 (v1): Valid UUID v1
❌ 550e8400-e29b-41d4-a716-446655440000 (v1): Expected version 1, got version
Quick Comparison of Methods
| Method | Validates Format | Validates Version | Strict Format | Performance |
|---|---|---|---|---|
uuid.UUID() | ✅ | ✅ (with check) | ❌ (lenient) | Fast |
uuid.UUID() + string comparison | ✅ | ✅ | ✅ | Fast |
| Regular expression | ✅ | ✅ (pattern-based) | ✅ | ⚡ Fastest |
Conclusion
Python provides flexible tools for validating UUIDs:
uuid.UUID()is the recommended approach for most cases. It's reliable, handles multiple formats, and lets you verify the UUID version.- Add a string comparison (
str(uuid_obj) == input) when you need to enforce the exact hyphenated format. - Regular expressions are ideal for lightweight format validation, extracting UUIDs from text, or scenarios where you want to avoid constructing UUID objects.
For production applications, always validate UUIDs at your system boundaries, API endpoints, form inputs, and data imports, to catch malformed identifiers before they cause downstream errors.