UUID.version / variant
The variant lives in the top bits of the 17th hex digit (the first of the fourth group): 8, 9, a or b means RFC 4122. Only then does the 13th digit (the first of the third group) mean something: it is the version. Any other variant gives version None.
Common call
u.version == 4
Returns
True for a uuid4; version is an int or None
Replaces
Reading str(u)[14] by hand
Watch out
A hand-typed UUID like 12345678-1234-5678-1234-… has variant RESERVED_NCS and version None
u.version · u.variant · uuid.RESERVED_NCS · uuid.RFC_4122 · uuid.RESERVED_MICROSOFT · uuid.RESERVED_FUTURE
→ int | None / str
Demo
Live evaluation
Type a UUID and see what kind it is.
Try:
Inputs
textstra UUID string
Code
import uuid u = uuid.UUID('16fd2706-8baf-433b-82eb-8c7fada847da') (u.version, u.variant)
Result
(4, 'specified in RFC 4122')
All zeros is variant RESERVED_NCS and all ones RESERVED_FUTURE, so both have version None. The COM GUID 00000000-0000-0000-c000-000000000046 (IUnknown) is in the Microsoft variant. In the last case the third group starts with 4, yet version is None: the fourth group starts with 1, so the variant is not RFC 4122 and the version digit does not count.
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| version | int | None | (int >> 76) & 0xf when the variant is RFC_4122, otherwise None. |
| variant | str | One of the four constants below, from the top bits of clock_seq_hi_variant. |
| RESERVED_NCS | str | 'reserved for NCS compatibility': top bit 0 (fourth group starts with 0 to 7). |
| RFC_4122 | str | 'specified in RFC 4122': top bits 10 (fourth group starts with 8, 9, a or b). Every UUID uuid1/3/4/5 make. |
| RESERVED_MICROSOFT | str | 'reserved for Microsoft compatibility': top bits 110 (starts with c or d). |
| RESERVED_FUTURE | str | 'reserved for future definition': top bits 111 (starts with e or f). |
Common patterns
Accept only random UUIDs
Reject IDs that were not made by uuid4 (for example a uuid1 that leaks a MAC address).
import uuid u = uuid.UUID(text) if u.version != 4: raise ValueError("expected a version 4 UUID")
Dispatch on the variant
Compare with the module constants, not with the literal strings.
import uuid if u.variant == uuid.RFC_4122: kind = f"RFC 4122 version {u.version}" else: kind = u.variant
Examples
1. A uuid4 is version 4
import uuid
uuid.uuid4().version
Returns
42. Name-based: 3 and 5
import uuid
(uuid.uuid3(uuid.NAMESPACE_DNS, 'x').version, uuid.uuid5(uuid.NAMESPACE_DNS, 'x').version)
Returns
(3, 5)3. The variant constants are strings
import uuid
uuid.RFC_4122
Returns
'specified in RFC 4122'4. All four
import uuid
[uuid.RESERVED_NCS, uuid.RFC_4122, uuid.RESERVED_MICROSOFT, uuid.RESERVED_FUTURE]
Returns
['reserved for NCS compatibility', 'specified in RFC 4122', 'reserved for Microsoft compatibility', 'reserved for future definition']5. Nil UUID: no version
import uuid
print(uuid.UUID(int=0).version)
Returns
None6. Microsoft variant
import uuid
uuid.UUID('00000000-0000-0000-c000-000000000046').variant
Returns
'reserved for Microsoft compatibility'7. version= sets both
import uuid
u = uuid.UUID(int=0, version=4)
(u.version, u.variant == uuid.RFC_4122)
Returns
(4, True)Pitfalls
1. Trusting the version digit alone
A UUID whose third group starts with 4 is not version 4 unless the variant is RFC 4122. version already checks that; a regex on the text usually does not.
str(u)[14]
import uuid str(uuid.UUID('12345678-1234-4678-1234-567812345678'))[14] == '4'
True
u.version
import uuid uuid.UUID('12345678-1234-4678-1234-567812345678').version == 4
False
2. Expecting an int for every UUID
version is None outside the RFC 4122 variant, so arithmetic or formatting with it can fail.
version + 0
import uuid uuid.UUID(int=0).version + 0
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
check variant
import uuid u = uuid.UUID(int=0) u.version if u.variant == uuid.RFC_4122 else 0
0
When to use
Use it
- Validating that an incoming ID is a uuid4 (or a uuid5 from your namespace)
- Telling Microsoft GUIDs and legacy NCS UUIDs apart from RFC 4122 ones
Reach for something else
- Checking the format of the text → UUID() parsing does that
- Hand-written regexes for the version → u.version
Notes
CPython impl
variant tests bits 0x8000, 0x4000 and 0x2000 of the clock_seq field (int >> 48) in turn; version returns int((self.int >> 76) & 0xf) only when variant == RFC_4122, else falls off the end (None)
Versions
3.13 knows versions 1 to 5 (UUID(version=6) raises "illegal version number"). The 3.14 docs list versions 1 through 8 and say RFC_4122 is kept for backward compatibility although RFC 9562 superseded RFC 4122
Nil and Max
All zeros (nil) and all ones (max) are special UUIDs; 3.14 adds them as uuid.NIL and uuid.MAX
FAQ
uuid.UUID(text).version returns 1, 3, 4 or 5 for UUIDs made by the standard algorithms, and None when the variant is not RFC 4122.