Is a UUID secure?

A v4 UUID is unguessable — roughly 1 in 5×1036. But an identifier is not a credential, and the versions that sort nicely are the ones that leak.

Unguessable, with one condition

v4: 122 random bits
    5.317e+36 possible values
    single blind guess ≈ 1.88e-37

v7: 48-bit timestamp + 74 random bits
    within one millisecond ≈ 5.29e-23

Both numbers are far past any brute-force reach. The condition attached to them is that the randomness must actually be cryptographic. A UUID built from Math.random() is not: V8 implements it with xorshift128+, a fast generator with 128 bits of internal state that was never designed to resist analysis, and published work has shown its outputs can be used to recover that state and predict what follows.

The dangerous part is that the result is indistinguishable by eye. A weak v4 has the same length, the same version digit and the same shape as a strong one. Use your platform's secure generator — crypto.randomUUID() in browsers and Node, uuid.uuid4() in Python, Guid.NewGuid() in .NET — and the guarantee holds.

An identifier is not a credential

This is where most UUID security discussions go wrong. Making a URL unguessable stops enumeration, which is a genuine improvement over a sequential integer. It does not make the URL secret, because URLs leak continuously: browser history, Referer headers, screenshots pasted into chat, server access logs, analytics pipelines, and anyone standing behind you.

If a UUID in the path is the only thing standing between a stranger and the data, then everyone who has ever seen that link has permanent access, and you have no way to revoke it. The check belongs on the server: does this requester have the right to see this record? Treat the identifier as an address, not a key.

What each version discloses

VersionUnguessableDiscloses
v4✅ 122 bitsnothing
v7✅ 74 bits per mscreation time (ms)
v1✅ but only via clock_seqcreation time + MAC address
v3 / v5❌ deterministiccomputable from the input

The v3 and v5 row deserves emphasis. They are hashes of a namespace and a name, so anyone who can guess the input can compute the identifier exactly. If your user IDs are v5 of the email address, then knowing someone's email means knowing their ID. That is fine for deduplication and wrong for anything that should be unpredictable.

Where a UUID is the wrong tool

Password reset tokens, email confirmation links and magic links all need properties a UUID does not carry: an expiry, single use, a binding to one account, and invalidation when circumstances change. You have to implement those regardless, and once you do, the identifier format stops mattering.

For these, generate bytes from your secure random source and — the part most often skipped — store the hash rather than the value. A leaked database of reset tokens is otherwise a leaked set of working credentials. See UUID v4 for what the format does guarantee, and UUID collision probability for the accidental-duplicate side of the question, which is a different problem from an adversarial one.

Frequently asked questions

Can a UUID be guessed?

A version 4 UUID, generated from a cryptographically secure source, cannot be guessed in any practical sense. It carries 122 random bits, which is about 5.3 × 10^36 possible values, so a single blind attempt succeeds with probability near 1.9 × 10^-37. Even a sustained campaign of billions of guesses per second gets nowhere. The caveat is that this holds only when the randomness is genuinely cryptographic. A UUID assembled from Math.random or a seeded pseudo-random generator can be far weaker than its length suggests, and the resulting value looks exactly the same, which is what makes the failure hard to notice. Published analysis of V8's xorshift128+ has shown its internal state can be recovered from a handful of outputs, so the weakness is practical rather than theoretical.

Is a UUID safe to use as a password reset token?

A v4 UUID has enough entropy, but it lacks everything else such a token needs. A reset token must expire, must be usable exactly once, must be tied to a specific account, and must be invalidated when the password changes or another reset is requested. None of that comes from the identifier — you have to build it, and if you are building it anyway there is no advantage to the UUID format. Use a random value from your platform's secure generator and store its hash, not the value, so a database leak does not hand over working tokens. The same reasoning applies to email confirmation and magic links, both of which are single-use credentials wearing the costume of a URL.

Does a UUID v7 leak information?

Yes, its creation time, to the millisecond. The first 48 bits are a Unix timestamp by design, and anyone holding the value can read them — our decoder does exactly that with no key. For an internal database key that is harmless. For an identifier exposed in a public URL it can be a real disclosure: signup times, order timestamps, or the interval between two events, which is sometimes enough to infer volume. Version 1 is worse, since it embeds both a timestamp and, traditionally, the generating machine's MAC address. If creation time is sensitive, use v4 — it is the only version that discloses nothing at all about when or where it was made.

Is a UUID enough to protect a private URL?

Unguessable is not the same as authorised, and conflating the two is the most common mistake here. An unguessable URL keeps strangers from finding a resource by enumeration, which is genuinely better than a sequential integer, but it does nothing once the URL escapes. URLs leak constantly — through browser history, Referer headers, shared screenshots, chat logs, server access logs and analytics. Treating a UUID as the access control means anyone who ever sees the link has permanent access. Check on the server that the requester may see the record, and treat the identifier as an address rather than a key. The distinction also gives you revocation, which an unguessable URL can never offer.

Which UUID version is the most secure?

Version 4, because it is the only one that reveals nothing. Its 122 bits are random and carry no timestamp, no hardware identifier and no ordering. Version 7 is nearly as unguessable but discloses creation time; within a single millisecond only 74 bits remain random, which is still far beyond reach at roughly 5.3 × 10^-23 per attempt, but the timestamp itself is the disclosure that matters. Versions 1 and 6 leak both time and node. Versions 3 and 5 are deterministic hashes, so anyone who can guess the input can compute the identifier — never use them for anything that should be unpredictable — if your user IDs are v5 of the email address, then knowing the email means knowing the ID.

References

Check what a UUID reveals by pasting it into the decoder — it reads the version and, for time-based versions, the creation time, with no key at all.