UUID v3 vs v5: Name-Based UUIDs Explained
By SimpleTools24Published 3 min read
UUID v3 and v5 are name-based: they combine a namespace UUID with a name, such as a domain or URL, and hash them to produce a UUID. The same namespace and name always give the same UUID, which makes them useful for stable, reproducible IDs. The difference is the hash: v3 uses MD5 and v5 uses SHA-1. RFC 9562 recommends v5 over v3, and both are preferable to inventing your own scheme. Neither hides the input if someone can guess it.
In this guide
How Name-Based UUIDs Work
- Pick a namespace UUID, either a standard one or your own.
- Take the name as bytes (usually UTF-8 text).
- Hash the namespace bytes followed by the name bytes: MD5 for v3, SHA-1 for v5.
- Take the first 128 bits of the hash, then set the version (3 or 5) and variant bits.
Example in Python:
import uuid
uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
# UUID('cfbff0d1-9375-5685-968c-48ce8b15ae17') -- same result every time
uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
# UUID('9073926b-929f-31c2-abc9-fad77ae3e8eb')Run it anywhere, on any machine, and you get the same values.
Standard Namespaces
RFC 9562 lists predefined namespace UUIDs for common kinds of names:
| Namespace | UUID | Use for |
|---|---|---|
| DNS | 6ba7b810-9dad-11d1-80b4-00c04fd430c8 | Domain names |
| URL | 6ba7b811-9dad-11d1-80b4-00c04fd430c8 | URLs |
| OID | 6ba7b812-9dad-11d1-80b4-00c04fd430c8 | ISO object identifiers |
| X.500 | 6ba7b814-9dad-11d1-80b4-00c04fd430c8 | X.500 distinguished names |
For your own data, generate one random UUID to serve as your application's namespace, store it in configuration, and use it consistently. Mixing namespaces produces different UUIDs for the same name.
v3 vs v5 Side by Side
| UUID v3 | UUID v5 | |
|---|---|---|
| Hash | MD5 | SHA-1 |
| Bits from hash | 128 of 128 (6 overwritten) | 128 of 160 (6 overwritten) |
| Recommendation | Legacy compatibility | Preferred |
| Deterministic | Yes | Yes |
| Security | Not a security feature | Not a security feature |
MD5 and SHA-1 both have known weaknesses as cryptographic hashes, but here they're used for distribution and determinism, not secrecy. Still, the RFC prefers SHA-1 (v5) and allows v8 for designs needing a modern hash such as SHA-256.
Good Uses for Name-Based UUIDs
- Stable IDs from natural keys: the same email, URL or product code always maps to the same UUID across services, without a lookup table.
- Idempotent imports: re-running an import produces the same IDs, so duplicates are easy to detect.
- Deduplicating URLs or resources: hash the canonical URL under the URL namespace.
- Cross-system references: two services can independently derive the same ID for the same entity.
Caveats
- Not secret. If someone can guess the name, they can compute the UUID. Don't use v3 or v5 to hide email addresses or other personal data.
- Not reversible, but guessable. You can't get the name back from the UUID; you can only test guesses.
- Input normalisation matters.
Example.comandexample.com, or URLs with and without a trailing slash, give different UUIDs. Normalise names before hashing. - Collisions. Different names producing the same UUID are theoretically possible but not a practical concern for normal use.
Identifying v3 and v5 UUIDs
The 13th hex digit is 3 or 5. In cfbff0d1-9375-5685-968c-48ce8b15ae17, the third group starts with 5, so it's v5. How to tell which version a UUID is explains the version and variant digits.
The UUID decoder identifies name-based UUIDs and their variant. It can't recover the original name, because the hash is one-way; to check a guess, generate the UUID from that namespace and name and compare. The GUID generator can create v3 and v5 values from a namespace and name, and UUID versions explained places them alongside the other versions. In Python, see how to generate a UUID in Python.
Choosing and Managing Your Own Namespace
For application data, create your own namespace UUID once:
import uuid
APP_NAMESPACE = uuid.UUID('3d6f0a2c-8b4e-4f1a-9c7d-5e2b1a0f9c84') # generated once, then fixed
def customer_uuid(email: str) -> uuid.UUID:
return uuid.uuid5(APP_NAMESPACE, email.strip().lower())Keep the namespace in configuration or code, never regenerate it, and document it. Changing it later changes every derived ID.
Name-Based IDs and Privacy
Because anyone with the namespace can recompute the UUID from a guessed name, a v5 UUID derived from an email address effectively identifies that person to anyone who knows the namespace and suspects the email. Don't treat it as anonymised data. If you need pseudonymous IDs, use a keyed hash (such as HMAC) with a secret key, or random IDs stored in a lookup table.
Frequently Asked Questions
Is UUID v5 random?
No. It's deterministic: the same namespace and name always produce the same UUID.
Can I get the original name from a v5 UUID?
No. You can only test guesses by generating UUIDs and comparing.
Should I use v3 or v5?
v5, unless you need compatibility with an existing v3 system.
Can I use my own namespace?
Yes. Generate a random UUID once and use it as your application's namespace.
Summary
v3 and v5 deterministically hash a namespace and name into a UUID. Prefer v5, normalise names before hashing, use your own namespace for your data, and never treat them as a way to hide information.
Related tools
Sources
- RFC 9562 – Section 5.3 UUID Version 3 and Section 5.5 UUID Version 5 – IETF (opens in a new tab)
Related articles
- UUID Versions ExplainedWhat each UUID version contains, how it's generated, and which ones to use for new systems.
- Generate a UUID in Pythonuuid4(), uuid7() on Python 3.14+, uuid5() for deterministic IDs, and converting UUIDs between strings, bytes and ints.
- How to Tell a UUID's VersionRead the version and variant digits by eye, with worked examples and code for checking them programmatically.