A UUID (universally unique identifier) is a 128-bit value that can be generated anywhere, by anyone, without checking with a central authority, and still be safe to treat as unique. Written out, it is 32 hexadecimal digits in five hyphen-separated groups of 8-4-4-4-12, like b3e1c9a4-2f6d-4c8b-a1e7-5d90f3c2b864. If you are asking what is a UUID for in practice: it lets separate servers, devices or offline apps create IDs independently without colliding. Microsoft calls the same thing a GUID.
If you just need a few, the UUID generator creates between 1 and 100 version 4 identifiers per run. If what you actually need is a secret, such as an API key or a password, use the password generator instead. The slug generator handles human-readable URLs, and the JSON formatter makes API responses full of IDs easier to inspect.
What is a UUID made of?
The current specification is RFC 9562, published in May 2024, which replaced the long-standing RFC 4122. Most of the 128 bits carry data, but two small fields sit in fixed positions in every identifier and tell you how it was produced:
| Position | In the example | Meaning |
| First digit of the third group | 4 in 4c8b | Version: how the value was generated |
| First digit of the fourth group | a in a1e7 | Variant: 8, 9, a or b means the standard layout |
| Everything else | Random or time-based bits | Depends on the version |
That means you can tell the version at a glance. xxxxxxxx-xxxx-4xxx-... is random; xxxxxxxx-xxxx-7xxx-... is time-ordered. Two special values exist as well: the Nil UUID, all zeros, and the Max UUID, all f, which RFC 9562 introduced. The standard asks generators to output lowercase and readers to accept either case.
UUID vs GUID
For practical purposes they are the same thing. GUID is Microsoft's name, and Windows tools tend to display it in uppercase inside braces: {B3E1C9A4-2F6D-4C8B-A1E7-5D90F3C2B864}. The one real difference shows up in binary form. Windows' GUID structure stores the first three fields in little-endian byte order, so if you move raw 16-byte values between a .NET or SQL Server system and something else and the first three groups come out byte-swapped, that is the reason.
The versions in plain terms
| Version | Built from | Sortable? | Notes |
| v1 | Timestamp plus node ID, usually a MAC address | Not as text | Can reveal which machine created it, and when |
| v3 / v5 | Namespace plus name, hashed with MD5 / SHA-1 | No | Same input always gives the same value |
| v4 | 122 random bits | No | By far the most common |
| v6 | v1 fields reordered | Yes | For compatibility with v1 systems |
| v7 | Unix time in milliseconds plus random bits | Yes | The recommended time-based choice |
| v8 | Free-form, vendor-defined layout | Depends on design | For custom schemes |
A version 2 also exists, tied to an old distributed computing security standard, but you will almost never meet it in modern software. RFC 9562 itself advises using v7 instead of v1 and v6 wherever possible.
Version 1: timestamp plus MAC address
The original version combines a 60-bit timestamp counting 100-nanosecond intervals since 15 October 1582, a clock sequence, and a node ID for the generating machine. In most implementations the node is the network card's MAC address, which means a v1 value can reveal which computer produced it and roughly when. Because the time fields are written low part first, sorting these values as text does not put them in chronological order either.
Version 4: random bits
Most identifiers you meet today are v4. Six of the 128 bits are reserved for version and variant, and the remaining 122 are random. Nothing leaks from the value, but there is no ordering either. The generator on this site produces this version, using crypto.randomUUID() where the browser offers it and the same secure random source, crypto.getRandomValues, where it does not. The values are created on your device and never sent to the server; the page only increments an anonymous usage counter.
Version 7: sortable by time
v7 puts the Unix time in milliseconds into the first 48 bits and fills the rest with random data. In 01a132dc-dfba-7aec-bf67-0d88cbe8fbc2, the first twelve digits (01a132dcdfba) decode to 13 October 2026, 01:24:58.426 UTC. A value generated a millisecond later sorts after it, both as text and as a number. That property largely solves the index problem described below. The trade-off is that anyone holding the value can read when the record was created; where that matters, stay with v4.
Collision probability, calculated properly
Can two generated values ever be identical? Technically yes. Practically, as long as they are generated correctly, it is not something you need to plan for. The math is the birthday problem: in a room of 23 people the chance that two share a birthday already passes 50%, because the probability grows with the number of possible pairs rather than with the number of people. Identifiers behave the same way.
- v4 has 122 random bits, so there are 2¹²², or about 5.3 × 10³⁶, possible values.
- The probability of at least one collision among n values is approximately n² / (2 × 2¹²²).
- For one billion values that works out to about 9.4 × 10⁻²⁰.
- You would need roughly 103 trillion values before the odds reach one in a billion.
- A 50% chance requires about 2.7 × 10¹⁸ values; a system producing a billion every second would take around 86 years to get there.
Real-world collisions come from bad randomness, not from the math. The usual culprits are homemade functions built on a non-cryptographic generator such as JavaScript's Math.random(), virtual machines cloned from the same snapshot that boot with identical random state, and forked processes that inherit a copy of the generator's state. Using your platform's standard function, backed by a cryptographic source, removes those risks.
What is a UUID not? It is not a secret
An identifier names something; it does not protect it. The security considerations in RFC 9562 say explicitly that implementations should not assume these values are hard to guess and should not use them as security capabilities. Even a v4 produced from a cryptographic source ends up in URLs, log files and browser history. For password reset links or API keys, generate a long, random, expiring token designed for that job.
There is a useful flip side. Unlike sequential integers, v4 values cannot be enumerated by walking /invoice/1041, /invoice/1042 and so on. That hides your record count and makes blind guessing impractical, but it is not a substitute for authorization. If a user somehow learns the ID of someone else's record, only an access check on the server will stop them.
UUIDs as database primary keys
| Property | INT / BIGINT | v4 | v7 |
| Size | 4 / 8 bytes | 16 bytes | 16 bytes |
| Where it is generated | In the database, centrally | Anywhere, no coordination | Anywhere, no coordination |
| Insert order | Increasing | Random | Increasing with time |
| Guessability | Trivial | Impractical | Timestamp visible, rest random |
| Merging datasets | Conflicts likely | Painless | Painless |
The big win is knowing a record's ID before it reaches the database. A mobile app can create records offline, servers in two regions can write to the same table, and two companies' customer lists can be merged, all without worrying about key conflicts.
The costs are size and index behavior. Storing the value as text in a CHAR(36) column turns 16 bytes of data into 36 characters and bloats every index that includes it. Use native types instead. PostgreSQL's uuid type is 16 bytes; since version 13 it can generate v4 with gen_random_uuid(), and from version 18 it can generate v7 with uuidv7(). In MySQL 8, use a BINARY(16) column with UUID_TO_BIN() and BIN_TO_UUID(); because MySQL's own UUID() returns v1, the second argument in UUID_TO_BIN(UUID(), 1) swaps the time fields to make the stored value index-friendly.
The other cost is randomness. Engines that cluster table data by primary key, such as InnoDB, write each new v4 row into a random spot in the index, which means more page splits and poorer cache use. Because v7 increases over time, new rows land at the end of the index and most of that cost disappears.
- For a new table that needs distributed ID generation, consider v7 as the primary key.
- If creation time must stay private, use v4, or keep an integer primary key internally and expose a separate v4 column.
- Always store the value in a native type or a 16-byte binary column; text is the last resort.
- Use one spelling (lowercase, hyphenated) in APIs and logs; most comparison bugs come from formatting differences.
A shorter form: 22 characters instead of 36
If the hyphenated form looks too long in a URL, encode the 16 raw bytes with base64url. b3e1c9a4-2f6d-4c8b-a1e7-5d90f3c2b864 becomes s-HJpC9tTIuh512Q88K4ZA, 22 characters instead of 36. Nothing is lost, but the format is non-standard, so both ends need conversion code and the database should still hold the 16-byte binary value.
Frequently asked questions
Should identifiers be uppercase or lowercase?
RFC 9562 asks generators to emit lowercase and readers to treat both cases as equal. Problems appear in code that compares them as plain strings: A1B2... and a1b2... are the same identifier but will not match. Normalizing before storage avoids the bug.
Can the same value be generated twice?
For correctly generated v4 values the chance is effectively zero; even across a billion of them it stays below 10⁻¹⁹. Real duplicates almost always trace back to a broken random generator or to code that accidentally assigns the same value to two records.
Is it safe to show an identifier in a URL?
As an identifier, yes; it reveals less than a sequential number does. It does not replace permission checks, though. If knowing the link should not be enough to see the record, enforce authorization on the server.
How many can I generate at once?
The tool on this site produces between 1 and 100 v4 values per run, with 5 as the default. If you need more, run it again or call your language's standard function from your own code.
For secrets rather than identifiers, strong passwords and secure identifiers picks up where this article stops. The encoding behind the 22-character form is explained in what Base64 is, and if you move ID-heavy records between spreadsheets and APIs, CSV vs JSON covers the conversion traps.