What a UUID decoder reveals
Every RFC 9562 UUID encodes structural metadata in fixed bit positions. A decoder reads those positions and surfaces:
| Field | Position in string | What it tells you |
|---|---|---|
| Version | Character 13 (first digit of group 3) | How the UUID was generated |
| Variant | Character 17 (first digit of group 4) | Which layout specification it follows |
| Timestamp | First 48–60 bits (version-dependent) | When it was created — v1 and v7 only |
| Random bits | Remainder | Payload data, no decoded meaning |
UUID versions and what they expose
Version 4 — random
550e8400-e29b-41d4-a716-446655440000
^ ^
4 a ← version 4, variant RFC 9562
A v4 UUID carries 122 bits of random data. Beyond the version and variant fields there is nothing to decode — the bits have no semantic meaning.
Version 7 — time-ordered
018c4a14-2d91-7abc-8def-000000000001
^^^^^^^^^^^^^ ^ ^
timestamp 7 8 ← version 7, variant RFC 9562
The first 48 bits (first 12 hex characters) encode a Unix millisecond timestamp:
018c4a14-2d91 → hex: 018c4a142d91
dec: 1700000000401
date: 2023-11-14T22:13:20.401Z
Version 1 — MAC address + time
Version 1 encodes a 60-bit timestamp in 100-nanosecond intervals since October 15, 1582. The bits are spread across the first three groups in a non-sequential order (time_low, time_mid, time_hi_and_version), making decoding more involved. It also embeds the MAC address of the generating machine in the last 12 hex characters — a privacy risk that is why v1 should not be used for new work.
How to decode in code
JavaScript — decode version and variant
function decodeUUID(uuid: string): { version: number; variant: string } | null {
const clean = uuid.replace(/-/g, '');
if (clean.length !== 32) return null;
const version = parseInt(clean[12], 16);
const variantNibble = parseInt(clean[16], 16);
let variant: string;
if ((variantNibble & 0b1000) === 0) variant = 'NCS (legacy)';
else if ((variantNibble & 0b1100) === 0b1000) variant = 'RFC 9562';
else if ((variantNibble & 0b1110) === 0b1100) variant = 'Microsoft (legacy)';
else variant = 'Reserved';
return { version, variant };
}
JavaScript — extract UUID v7 timestamp
function decodeV7Timestamp(uuid: string): Date | null {
const clean = uuid.replace(/-/g, '');
if (clean.length !== 32 || clean[12] !== '7') return null;
// First 48 bits = 12 hex chars = Unix ms timestamp
const ms = parseInt(clean.slice(0, 12), 16);
return new Date(ms);
}
decodeV7Timestamp('018c4a14-2d91-7abc-8def-000000000001');
// → Date: 2023-11-14T22:13:20.401Z
Python
import uuid
def decode_uuid(value: str) -> dict:
u = uuid.UUID(value)
return {
'version': u.version,
'variant': str(u.variant),
'int': u.int,
'hex': u.hex,
}
# For v7, extract timestamp manually:
def decode_v7_timestamp(value: str) -> int:
u = uuid.UUID(value)
assert u.version == 7
# Top 48 bits are the Unix ms timestamp
return u.int >> 80
Go
import (
"github.com/google/uuid"
"time"
)
func DecodeV7Time(s string) (time.Time, error) {
u, err := uuid.Parse(s)
if err != nil {
return time.Time{}, err
}
t, err := u.Time() // only valid for v1 and v7
return t, err
}
Bit layout by version
UUID v4 — 128 bits
┌────────────────────────┬────┬──────────────────┬──┬──────────────────────┐
│ random (48 bits) │ver │ random (12 bits) │var│ random (62 bits) │
└────────────────────────┴────┴──────────────────┴──┴──────────────────────┘
UUID v7 — 128 bits
┌────────────────────────┬────┬──────────────────┬──┬──────────────────────┐
│ unix_ts_ms (48 bits) │ver │ rand_a (12 bits) │var│ rand_b (62 bits) │
└────────────────────────┴────┴──────────────────┴──┴──────────────────────┘
↑ sortable timestamp ↑ RFC 9562 variant (10xx)
What decoding cannot tell you
- Who created the UUID — v4 is pure random, v7 reveals when but not which system
- What entity it refers to — a UUID is an opaque identifier; the meaning lives in your schema
- Whether it is from your system — any v7 UUID from any system with the same timestamp will decode the same way
Related tools
- UUID Validator — verify a UUID is well-formed before decoding
- UUID Converter — convert the UUID to binary, hex, or URN after decoding
- Glossary: Variant — deep dive on the variant bits
Frequently asked questions
What information can you extract from a UUID?
From the UUID string alone you can read the version (digit at position 13) and variant (digit at position 17). For v1 and v7 you can also extract a timestamp — v1 embeds a 60-bit 100-nanosecond timestamp, v7 embeds a 48-bit Unix millisecond timestamp. v4 carries only random bits beyond the version and variant fields.
How do I extract the timestamp from a UUID v7?
Take the first 12 hex characters of the UUID (before the first hyphen, plus the first 4 of the second group), convert to a 48-bit integer, and that value is the Unix timestamp in milliseconds. For example: parseInt(uuid.replace(/-/g, '').slice(0, 12), 16) gives milliseconds since the Unix epoch.
Can you decode a UUID v4 to get the original random bytes?
Yes — the 122 random bits are recoverable from the UUID string itself. Strip the hyphens, parse as hex, then mask out the 4 version bits and 2 variant bits. The result is the 122-bit random payload, though it carries no additional meaning beyond randomness.