UUID Generator: Create v1, v3, v4, v5 and Nil IDs in One Batch

A UUID is the quiet workhorse behind a lot of software you touch every day: the id of the row you just inserted, the name of the file your build system wrote, the token in a URL you copied from a dashboard. The format looks arbitrary until you need to produce one by hand, and that is usually the moment someone reaches for a UUID generator. The page you are on does that job, and it also covers the neighbouring problem that shows up right after: valid-looking test data for bank accounts, tax numbers and national IDs.

This guide walks through the five versions the generator produces, when each one is the right call, what the batch controls actually give you, and why a generated value that does not pass its own checksum is worse than no value at all.

What a UUID is, beyond the 36 characters

Every UUID is 128 bits of data written as 32 hexadecimal digits in the pattern 8-4-4-4-12, with four hyphens for readability. The hyphens carry no meaning, and the underlying value is 16 bytes whether you display it with dashes or without. Two of those bits describe the variant and four describe the version, which leaves 122 bits for the payload in the common version 4 case.

The version digit sits at the start of the third group and the variant bits at the start of the fourth, which is why a v4 value always shows a 4 in that position followed by one of 8, 9, a or b. Once you know that, you can read a UUID by eye and tell how it was made, and the generator here sets those bits for you rather than pasting a random hex string and hoping.

What a UUID is not is a guarantee of uniqueness. It is a probability argument: with 122 random bits the space is 2^122, roughly 5.3 × 10^36 values, and the birthday bound puts a 50 percent chance of any collision at about 2.7 quintillion generated values. Generating a billion per second, you would need 86 years to get there. Real duplicates in production come from implementation mistakes, such as a seeded pseudorandom generator or a database column that trims the value, not from the mathematics.

The five versions this generator produces

The version selector covers what RFC 4122 defined and what people still use in schemas today, plus the nil value that marks an empty field.

Version Basis Payload Repeatable Typical use
v1 Timestamp and node 60-bit timestamp, clock sequence, node No, time moves Legacy systems that sort by creation
v3 MD5 of namespace and name 122-bit hash Yes, same input gives same UUID Deterministic mapping in old code
v4 Random 122 random bits No Primary keys, tokens, fixtures
v5 SHA-1 of namespace and name 122-bit hash Yes, same input gives same UUID Stable IDs derived from names
nil Constant All zeros Always Placeholder for an absent value

Version 1 combines a 100-nanosecond timestamp since 1582 with a clock sequence and a node identifier. It is sortable by creation time, which was useful when the format was designed, but it leaks when a value was made and, in its original form, which machine made it. Version 3 hashes a namespace UUID plus a name with MD5, and version 5 does the same with SHA-1. MD5 collision attacks have been practical since 2004, so v3 exists for compatibility, and new systems should pick v5 when they need a repeatable identifier.

Version 4 is the default for most work because it carries no information at all: no timestamp, no machine identity, no input. Nil is the all-zero value, 00000000-0000-0000-0000-000000000000, and it exists so a column can say "no identifier yet" without a null check in every query. All five come from the same selector, and switching between them costs one click.

Choosing a version without overthinking it

The short answer for a new table is version 4, or version 7 if you are storing the value in a native UUID column on a database that benefits from append-friendly keys. Version 7 puts a 48-bit millisecond timestamp in the high bits, so rows insert near-sequentially and the B-tree pages fill in order. The generator exposes v7 through the international format list rather than the version selector, because it belongs to the later RFC 9562 family, and it sits next to ULID and NanoID for exactly that reason.

Pick version 5 when the identifier has to be derived rather than invented. A typical case is an import that maps an email address to a user row: hash the address with a fixed namespace, get the same UUID on every run, and a repeated import updates the existing row instead of creating a twin. Version 1 shows up in older schemas where a creation-time ordering was baked into the key, and it is worth keeping in mind that two values from the same millisecond on the same host still differ because of the clock sequence.

The one thing to avoid is mixing versions inside a single column without a reason. A validator that expects a version digit of 4 will reject a v7 value, and a query that sorts by v4 keys gives you nothing useful about insertion order. Decide once, document the choice in the schema, and let the generator produce values that match it.

Batch output and the quantity slider

The slider runs from 1 to 100 values per run. That ceiling is deliberate: 100 identifiers is enough to seed a fixture file, fill a paginated test page, or paste into a SQL insert without turning the output panel into a wall of text. If a load test needs ten thousand values, run the generator again or wrap the page in a loop from your test harness.

Each generated value stays in the list with its own copy control, and the whole batch can be copied or downloaded as a file. That matters more than it sounds, because a common failure in test setups is a value that gets copied with a trailing space or a lost hyphen, and the field validates it as malformed. Taking the batch as a file avoids the clipboard entirely.

For v3 and v5, the batch is the same value repeated, and that is correct rather than a bug: those versions are deterministic in the namespace and name pair, so changing the quantity does not change the output. Use the quantity slider with v1, v4, v7, ULID or NanoID, where every value is meant to be distinct.

Beyond UUIDs: 196 identifier formats across 76 countries

The second half of the page solves a problem that shows up the moment your test suite touches a form with a required bank field. There are 196 formats in total. 57 of them are international and split into eight groups: vendor identifiers such as UUID v7, ULID, KSUID, NanoID and CUID2; GS1 keys and barcode formats; bibliography formats including ISBN; finance formats such as IBAN, BIC, ISIN and LEI; transport identifiers including VIN and plates; telecom identifiers including IMEI and phone numbers; geography formats such as geohash; and 16 crypto address formats.

The other 139 are national, spread over 76 countries and grouped by country name. Germany alone has five formats, Austria, Australia and Belgium have three each. Each entry shows the local name, the abbreviation and the alphabet it uses, so a Portuguese NIF and a French SIRET are not confused for one another. A search box filters across names, countries and abbreviations, which is faster than scrolling a list of 139 entries when you already know you need an Angolan tax number.

These values are synthetic. They follow the length and alphabet rules of the real format and pass the checksum where the format defines one, which is what a validator on the other side of the form will test. They do not belong to a person or an account, and they should not be sent to a live payment system.

Why validation matters more than generation

Generating a string of the right length is easy, and that is exactly why so much test data is wrong. An IBAN is not just a country code and a run of digits: positions three and four hold check digits computed with the MOD-97 algorithm over the rest of the value, and the length is fixed per country. Without the checksum the value fails the first real validation it meets, and the test tells you nothing about your own code.

The same pattern repeats across formats. EAN and UPC barcodes carry a check digit computed with alternating weights. ISIN and LEI values carry check digits derived from letter-to-number conversion. National tax numbers have their own length and alphabet rules, and many add a checksum of their own. The generator validates each value after producing it and flags the result, so a format that is present but mis-implemented shows up in the output rather than in a failing build three days later.

There is a limit worth stating plainly: a passing validation proves the structure, not that the bank code is current or that the account exists. Structural validity is what a form checks before it submits, and that is the barrier this page is built to clear.

Deterministic IDs and idempotent imports

The version 5 mode deserves a longer look because it changes how an import behaves. The default namespace is the DNS namespace from the specification, 6ba7b810-9dad-11d1-80b4-00c04fd430c8, and you can paste any UUID in its place. Give the tool the same namespace and name twice and you get the same identifier, byte for byte, on any machine.

That property turns a messy import into an idempotent one. Derive the row key from the natural key of the record, an email, a product code, a URL, and the second run of the importer updates instead of duplicating. The same trick gives you stable cache keys, stable file names for generated exports, and stable identifiers for seeded demo data that reference each other across tables.

The trade-off is that the value is a pure function of its inputs. Anyone who knows the namespace and the name can compute the same UUID, so it is not a secret and should not be used as one. Use it where you want repetition, and use v4 or v7 where you want unpredictability.

Where the values live

Everything on the page runs inside the browser. Generation uses bundled libraries, validation runs locally, and nothing is uploaded, so a batch of test identifiers never appears in a server log. That is a practical advantage when the data resembles real financial or identity numbers, since the whole point of using synthetic values is to keep them out of places where they could be mistaken for genuine records.

The flip side is that nothing survives a page reload. Copy the values or download the batch before you navigate away, especially if you generated a long list for a migration script.

Frequently Asked Questions

Are v3 and v5 values safe to use as passwords or tokens?

No. Both are hashes of a name and a namespace, and anyone with those two inputs can recompute the value. They are meant for stable identifiers, not for anything that has to stay secret.

Why does the v4 output look random but the fourth group always starts with 8, 9, a or b?

Those two leading bits encode the variant, and the version digit ahead of them is the 4 of version 4. The pattern is the format working correctly, not a restriction on the random part.

Can I generate more than 100 identifiers in one run?

The slider stops at 100 per run. For bigger sets, run the generator again or call the underlying library from your test harness, which is faster than copying several batches by hand.

Does the generator work offline?

The page runs in the browser and needs its libraries loaded once, so once the page is open a generation run does not depend on a server response. Reloading the page does require a connection.

What happens if I leave the namespace field empty for v3 or v5?

The generator falls back to the DNS namespace and uses whatever name you typed. If the namespace text is present but malformed, the run stops with an error instead of returning a value that would fail validation later.

Are the national ID numbers valid in the real world?

They pass the structural and checksum rules of their format, which is what a form tests. They are not issued to anyone, and they must not be used in live banking or government systems.

Why is the same ULID different on every run?

ULID starts with a millisecond timestamp, so two values created at different moments differ even though both are sortable. Only the name-based UUID versions are repeatable by design.

Can I use these identifiers in production data?

Use real sources for real records. Generated values are test data: seeds, fixtures, sandbox transfers, UI placeholders and load tests.

Vladimir Starkov
Vladimir Starkov

Stockholm, Sweden · SO reputation 19943 · Badges: 8🥇63🥈116🥉 · SO member since 2011