← Back

UUIDs Are Just Numbers

If you've worked with databases or APIs, you've probably seen UUIDs everywhere. Something like:

550e8400-e29b-41d4-a716-446655440000

They look like some arcane string format with dashes in specific places. But here's the thing: a UUID is just a 128-bit number, and the familiar string representation is just that number written in base 16 (hexadecimal) with a few hyphens thrown in for readability.

What's actually in a UUID?

UUID stands for Universally Unique Identifier. The spec (RFC 9562) defines it as a 128-bit value — that's 16 bytes, or 32 hexadecimal digits. The canonical string form groups those 32 hex digits into five sections separated by hyphens:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
8 chars  4    4    4    12 chars

If you strip the hyphens, you're left with exactly 32 hex characters. Each hex character encodes 4 bits, so 32 × 4 = 128 bits. That's it. The entire UUID is one big number.

Hexadecimal is just base 16

We normally write numbers in base 10 (decimal), using digits 0 through 9. Hexadecimal (base 16) extends that with the letters af to represent values 10–15:

Hex digit Decimal value
090–9
a10
b11
c12
d13
e14
f15

So the UUID 550e8400-e29b-41d4-a716-446655440000 is the hex number 550e8400e29b41d4a716446655440000, which in decimal is:

113059749145936325402354257176981405696

That's a very large number, but it's still just a number. You can do arithmetic on it, compare it, sort it — whatever you want.

The anatomy of a version 4 UUID

Not all 128 bits are random. A few bits are reserved to encode metadata. In the most common variant (version 4, the random kind), the structure looks like this:

550e8400-e29b-41d4-a716-446655440000
                  ^    ^
                  |    |
                  |    variant (bits 64-65): always 0b10
                  version (bits 48-51): always 0b0100 (4)

The 4 in the third group tells you it's version 4. The leading a (binary 1010) of the fourth group starts with 10, marking the RFC 4122 / RFC 9562 variant. Everything else is random. That leaves 122 bits of randomness, which gives you about 5.3 × 1036 possible UUIDs — plenty to avoid collisions in practice.

Converting between representations

Because a UUID is just a number, converting between the string form and an integer is straightforward. In Python:

import uuid

u = uuid.UUID("550e8400-e29b-41d4-a716-446655440000")

# UUID to integer
print(u.int)
# 113059749145936325402354257176981405696

# Integer back to UUID
print(uuid.UUID(int=u.int))
# 550e8400-e29b-41d4-a716-446655440000

You can also get the raw 16 bytes:

print(u.bytes)
# b'U\x0e\x84\x00\xe2\x9bA\xd4\xa7\x16DfUD\x00\x00'

print(len(u.bytes))
# 16

The string, the integer, and the byte sequence are all the same value — just different ways of writing it down.

Why does this matter?

Understanding that UUIDs are just numbers clears up a lot of practical questions:

Next time you see a UUID, remember: strip the dashes, and you're looking at a 32-digit hexadecimal (base 16) number. That's all there is to it.