Skip to main content

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:

VersionGeneration MethodUse Case
1Timestamp + host MAC addressTime-ordered identifiers
3MD5 hash of namespace + nameDeterministic, name-based
4Randomly generatedGeneral-purpose, most common
5SHA-1 hash of namespace + nameDeterministic, name-based (more secure than v3)
tip

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.

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

  1. uuid.UUID(uuid_string) attempts to parse the input string.
  2. If the string doesn't conform to UUID format, a ValueError is raised and caught.
  3. If a specific version is provided, the function additionally verifies that the parsed UUID matches that version.
Watch Out: uuid.UUID() Is Lenient with Formatting

The 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:

SegmentMeaning
[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
note

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

MethodValidates FormatValidates VersionStrict FormatPerformance
uuid.UUID()✅ (with check)❌ (lenient)Fast
uuid.UUID() + string comparisonFast
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.