What a UUID is, and why 1, 2, 3 stops working
A UUID is a 128-bit identifier written as 32 hexadecimal digits in five hyphen-separated groups, 8-4-4-4-12, for example 550e8400-e29b-41d4-a716-446655440000. The point of the format is that any machine can mint one on its own, with no coordination and no round trip to a central allocator, and still be confident nobody else produced the same value. This page builds them with crypto.randomUUID() and crypto.getRandomValues(), the browser APIs intended for cryptographic use.
The obvious alternative, an auto-incrementing integer, needs a single writer handing out numbers, so an offline client or a second region cannot create a row and reconcile later, and merging two databases that both started at 1 turns into a re-keying project. The values are also public arithmetic: a customer who sees /invoices/1042 learns roughly how many invoices you have issued and can try 1041.
Six of the 128 bits are spoken for: four mark the version and two the variant, which is why every v4 here has a 4 at the start of the third group and an 8, 9, a or b at the start of the fourth. That leaves 122 random bits, and by the birthday bound you would need on the order of 2^61 values before a repeat became likely. RFC 4122 defined the format in 2005; RFC 9562 replaced it in May 2024 and made v6, v7 and v8 official.
Which version to generate
This page generates the two versions worth choosing between for new work. The rest are here so you recognize them in someone else’s data.
- v4, random: 122 bits of randomness and nothing else. No ordering, no embedded metadata, the widest support. Pick it for public-facing identifiers and anywhere the creation time should stay private.
- v7, time-ordered: a 48-bit Unix millisecond timestamp followed by randomness, so later values sort after earlier ones as text and as raw bytes. The better default for database primary keys and event ids.
- v1, time and MAC address: the original layout. It embeds the network card of the generating machine and does not sort by time. Worth recognizing because
UUID()in MySQL returns one. - v3 and v5, name-based: a hash of a namespace plus a name, MD5 for v3 and SHA-1 for v5. The same input always gives the same UUID, which is how you derive a stable identifier from a URL. Not random, so never where unguessability matters.
- v6, v8, Nil and Max: v6 is v1 reordered so it sorts, v8 is an empty slot a vendor fills itself, and the all-zero Nil and all-f Max are reserved sentinels, not identifiers to hand out.
How to generate a batch for seed data or a migration
- Choose the version. If the identifiers go into a table you will query in creation order, pick v7; otherwise v4 is fine.
- Set How many to the number of rows you need. The field takes 1 to 1000 and the list regenerates as the value changes.
- Press Regenerate for a fresh set with the same settings. Nothing is remembered, so a reload gives different values.
- Press Copy all. The identifiers arrive one per line, which is what a spreadsheet column, a SQL
VALUESlist and most CSV importers expect. The button on a row copies just that one. - Paste them somewhere durable before you close the tab, because nothing here is stored.
For test fixtures, committing literal values beats calling a generator at test time: a failing test then points at a constant you can search for.
How to use v7 as a primary key without regrets
- Declare the column with the 16-byte native type where one exists:
uuidin PostgreSQL,uniqueidentifierin SQL Server,BINARY(16)in MySQL, aBLOBorTEXTcolumn in SQLite. - Generate the value in the application unless your database has a v7 function. Knowing the id before the insert lets you build a whole object graph in memory and write it in one transaction.
- Keep it out of public URLs if the creation time is sensitive. A v7 announces when a row was made, and a run of them announces how fast rows are being made.
- Give people a separate short reference, such as an invoice number. Nobody wants to dictate 36 characters over the phone.
- Index deliberately. Every secondary index carries a copy of the 16-byte key, so six indexes pay that cost six times.
Getting the identifiers where you need them
There is no download button here on purpose: a list of UUIDs is small enough that the clipboard beats a file. Copy all joins them with newlines, so where they land decides what you get.
- Spreadsheets: a newline-separated paste fills one cell per row in Excel, Numbers or Google Sheets.
- Code and SQL: paste into your editor and use multi-cursor editing to wrap each line in quotes and commas. Editors based on VS Code drop a cursor on every line with Ctrl+Alt+Down or Cmd+Option+Down.
- Terminals: Ctrl+Shift+V on most Linux terminals, Cmd+V on macOS, Ctrl+V or right click in Windows Terminal. A multi-line paste can run immediately in a shell, so go through an editor if you are unsure what you copied.
- iPhone and Android: press and hold in the field and tap Paste. iOS asks permission the first time one app reads what another copied; on Android, Gboard keeps a clipboard history behind the icon on its toolbar.
Generating and storing UUIDs in each stack
Every ecosystem has a built-in v4; support for v7 is newer and uneven. These notes describe the situation at the time of writing, so check what your own versions ship.
- JavaScript and TypeScript:
crypto.randomUUID()returns a v4 in browsers and in Node, but needs a secure context, so it isundefinedon a plain HTTP page. There is no built-in v7; take it from a library such asuuid, or build it oncrypto.getRandomValues()as this page does. - PostgreSQL: a native
uuidtype stored as 16 bytes, withgen_random_uuid()built in since version 13 for a v4. Recent versions adduuidv4()anduuidv7(); if yours lacks them, generate v7 in the application. - MySQL and MariaDB: no UUID column type, and
UUID()returns a v1 that does not sort by time. The usual pattern isUUID_TO_BIN(uuid, 1)into aBINARY(16)column, where the second argument swaps the time fields so the stored bytes sort, withBIN_TO_UUID(id, 1)on the way out. Use the same flag on both sides or you get scrambled values. - SQLite and SQL Server: SQLite has neither a UUID type nor a generator, so store text or a 16-byte
BLOBand generate in the application. SQL Server hasuniqueidentifier, withNEWID()for a random value andNEWSEQUENTIALID()for one that increases within a session. - Python, Java and Go:
uuid.uuid4()andUUID.randomUUID()ship in the standard library, and Go usually reaches forgithub.com/google/uuid, which also has v7. Time-ordered versions reached the Pythonuuidmodule only recently and the JDK class has no v7 factory, so check your version. - .NET:
Guid.NewGuid()is a v4 and recent versions add a v7 factory. Watch the byte order:Guid.ToByteArray()writes the first three fields little-endian, so sharing aBINARY(16)column with another language silently produces identifiers that no longer match.
Comparison is the other trap. UUIDs compare case-insensitively as UUIDs but not as strings, so normalize to lowercase with hyphens on the way in and decide once whether your API returns the hyphenated form or the bare 32 characters.
Limits, privacy and honest caveats
What leaves your browser: nothing. Every identifier here is produced locally by crypto.randomUUID() or crypto.getRandomValues(), and none is transmitted, logged or stored. None can be recovered either, so copy what you need before the tab closes.
A UUID is an identifier, not a credential. The 122 random bits in a v4 are genuinely hard to guess, but the value is designed to be shared, and code that treats knowledge of an id as proof of access is one leaked log line from a breach. A v7 is weaker still in that respect, because the first half is a timestamp anyone can read. Authorize on the server and use purpose-built secrets for tokens.
Time-ordering has a privacy cost. Publishing v7 identifiers publishes your creation timestamps, and a handful of them reveals your rate of activity. If that matters, keep the v7 as an internal key and expose a v4 or an opaque slug.
Uniqueness depends on good randomness. The collision argument assumes a cryptographic random source. It holds here and in the standard library functions above, but not for anything built on Math.random().
They are hard on people. Thirty-six characters with no redundancy cannot be read aloud or typed reliably from a printout, and screen readers announce them one character at a time. Where a human handles the reference, pair the UUID with a short human code.
Frequently asked questions
What is a UUID, and is a GUID the same thing?
A UUID is a Universally Unique Identifier: 128 bits written as 32 hexadecimal digits in the 8-4-4-4-12 pattern, for example 550e8400-e29b-41d4-a716-446655440000. GUID (Globally Unique Identifier) is the Microsoft name for the same 128-bit value, and the two words are interchangeable in practice. The format is standardized in RFC 9562, which replaced RFC 4122 in 2024.
Should I generate v4 or v7?
Use v7 for anything that becomes a database primary key or a sort key, because the first 48 bits are a Unix millisecond timestamp, so new rows land at the end of the index instead of scattering across it. Use v4 when the value is a public handle and you would rather not publish the moment the record was created. Both are generated here with the same cryptographic randomness.
Can two UUIDs ever collide?
In theory yes, in practice no. A v4 carries 122 random bits, because 6 bits are fixed for the version and variant markers. By the birthday bound you would need to generate on the order of 2^61 values, roughly 2.3 quintillion, before a collision becomes likely. That is why nodes can mint identifiers locally without asking a central allocator for permission.
Is a UUID a secret? Can I use one as a session token?
Treat it as an identifier, not as a credential. A v4 from a cryptographic random source has 122 unguessable bits, which is strong, but the structure is public and anyone who sees one UUID learns the version and variant of the rest. A v7 additionally reveals when it was created, and the legacy v1 embeds a MAC address. For session tokens, API keys and password reset links, generate a dedicated random secret and check authorization on the server.
Why do all these UUIDs have a 4 in the same position?
That digit is the version marker. The first hexadecimal digit of the third group is 4 for a v4 and 7 for a v7, and the first digit of the fourth group is the variant, normally 8, 9, a or b. Those 6 fixed bits are the difference between 128 bits of storage and 122 bits of actual entropy, and they are how a parser tells the versions apart.
How should I store a UUID in a database?
Store the 16 raw bytes wherever the engine offers a native type. PostgreSQL and SQL Server have one (uuid and uniqueidentifier). MySQL and SQLite do not, so people use BINARY(16) or a BLOB and convert at the edges. Storing the text form costs 36 bytes per row plus index overhead, which is more than twice the binary size, though it is far easier to read in a console and is a reasonable trade for small tables.
Do UUID primary keys really slow a database down?
Random ones can. A v4 lands at an unpredictable point in a B-tree index, so inserts touch pages all over the index, dirty more of them and split them more often. A v7 is close to monotonic, so inserts append and the working set stays small. The other cost is size: 16 bytes against 4 or 8 for an integer, repeated in every secondary index that references the key.
How do UUIDs compare with ULID and Nano ID?
A ULID is also a 128-bit time-ordered identifier but is written in 26 Crockford base32 characters instead of 36, so it is shorter and case insensitive. Nano ID is a shorter URL-safe random string, 21 characters by default, with no standard structure at all. Since RFC 9562 gave UUID v7 an official time-ordered layout, the practical reason to reach for ULID is mostly the shorter text form.
Can I read the creation time back out of a v7?
Yes, and that is a feature and a leak at the same time. The first 12 hexadecimal digits are the Unix timestamp in milliseconds, so parsing them as a big-endian integer and passing the result to your date library recovers the moment of generation. Anyone holding the identifier can do the same, so do not use v7 where the creation time is sensitive or where sequential-looking values invite enumeration.
Does anything I generate here leave my browser?
No. The identifiers come from crypto.randomUUID() and crypto.getRandomValues() inside the page, and nothing is uploaded, logged or stored on a server. Reloading the tab throws them away, so copy what you need first. Both APIs require a secure context, which means HTTPS or localhost.
Sources
- IETF, RFC 9562, Universally Unique IDentifiers (UUIDs) (the current standard: the 8-4-4-4-12 text form, version and variant bits, and the v6, v7 and v8 layouts).
- IETF, RFC 4122 (the 2005 specification that RFC 9562 obsoletes, and where v1, v3, v4 and v5 were defined).
- MDN, Crypto.randomUUID() and Crypto.getRandomValues() (the two browser APIs this page uses, including the secure-context requirement).
- Database and runtime behavior comes from the reference manuals of each product: the PostgreSQL data types and functions chapters, the MySQL miscellaneous functions page for
UUID_TO_BIN, the SQL Server documentation foruniqueidentifier, and the standard library documentation for Python, Java and .NET. Version support changes, so check the manual for the version you run.
More developer tools
When an identifier arrives inside an API response, the JSON formatter makes it readable, and the JWT decoder shows the claims of a token that carries one as a subject. For values traveling in a URL or a header, see the URL encoder and the Base64 encoder. If what you actually need is a secret rather than an identifier, generate it with the password generator.
Related tools
- JSON Formatter and Validator
Pretty-print or minify JSON in your browser with 2-space, 4-space or tab indentation.
- Base64 Encode and Decode
Convert text to Base64 and back with full UTF-8 support, so accented letters, CJK and emoj…
- JWT Decoder
Paste a JSON Web Token to decode its header and payload, see the expiry (exp) as a readabl…
- URL Encoder and Decoder
Percent-encode or decode URLs and query strings with encodeURI or encodeURIComponent semantics.
- Random Password Generator
Generate a cryptographically random password in your browser: choose the length (4 to 64),…
Privacy: every UUID is generated in your browser with crypto.randomUUID() and crypto.getRandomValues() and is never sent to a server, stored or logged. Analytics records only that identifiers were generated, with the version and the count, plus a count of copy button presses. The identifiers themselves are never included.
