UUID / ULID Generator & Validator — Free HTML CSS JS Snippet

UUID / ULID Generator & Validator · Dev · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Real cryptographic randomness via crypto.randomUUID() / crypto.getRandomValues(), never Math.random()
Correct RFC 4122 UUID v4 bit-pattern construction (version nibble, variant bits) when using the manual fallback path
Genuine ULID implementation: 48-bit millisecond timestamp + 80 bits of randomness, Crockford Base32 encoded
Bulk generation of up to 100 identifiers at once in either format
One-click copy-to-clipboard for the current single generated value
Strict format validator distinguishing real UUIDs (checking version/variant nibbles) from merely hex-shaped lookalikes
ULID validator decodes and displays the exact embedded creation timestamp as an ISO date
Entirely client-side — every identifier is generated and validated locally, nothing is transmitted

About this UI Snippet

UUID v4 / ULID Generator & Validator — Real crypto.getRandomValues Entropy, Crockford Base32 Timestamp Encoding

Screenshot of the UUID / ULID Generator & Validator snippet rendered live

Both UUIDs and ULIDs solve the same underlying problem — generating an identifier unique enough to assign without checking a central database — but they trade off differently between randomness and sortability. This snippet generates both formats correctly, using real cryptographic randomness from the Web Crypto API rather than Math.random(), and includes a validator that recognizes and decodes both.

UUID v4: 122 bits of real entropy, RFC 4122 formatted

genUuid4() prefers the browser's native crypto.randomUUID() when available, which is the most correct implementation possible — it's provided directly by the browser's cryptographic subsystem. As a fallback for older environments, the function generates 16 random bytes via crypto.getRandomValues() (a cryptographically secure random number generator, unlike Math.random() which is not specified to be unpredictable), then manually sets the two fixed bit patterns RFC 4122 requires: byte 6 is masked to 0x40 in its top nibble to encode "version 4," and byte 8 is masked to 0x80/0xa0-range to encode the "variant" bits. Only 122 of the 128 bits are actually random — the other 6 are fixed by the version and variant markers — which is why UUID v4 collision probability calculations use 122, not 128, bits of entropy.

ULID: sortable by design, using Crockford's Base32

A ULID (Universally Unique Lexicographically Sortable Identifier) deliberately encodes the current timestamp into its first 48 bits (10 characters), followed by 80 bits (16 characters) of randomness — 26 characters total. Because the timestamp comes first and is encoded in a way that preserves ordering, ULIDs generated later always sort after ULIDs generated earlier when compared as plain strings, which a random UUID cannot do. genUlid() builds the 48-bit millisecond timestamp as 6 raw bytes, then encodes both the timestamp bytes and 10 additional random bytes through encodeCrockford(), which converts the bit string 5 bits at a time into Crockford's Base32 alphabet — a 32-character set (0-9, most letters, deliberately excluding I, L, O, and U to avoid visual confusion with 1, 0, and profanity) chosen specifically for human readability and reduced transcription errors versus standard Base64.

Why 5-bit chunks, not the usual base64's 6-bit chunks

Base32 uses a 32-symbol alphabet, and 32 = 2^5, so each output character encodes exactly 5 bits of input — that's why encodeCrockford() walks the bit string in slices of 5 (bits.slice(i, i + 5)) rather than the 6-bit slices you'd use for standard Base64's 64-symbol alphabet. 128 bits total (48 timestamp + 80 random) divided by 5 bits per character comes out to 25.6, which is why the timestamp portion is deliberately truncated to exactly 10 Crockford characters (50 bits' worth of capacity holding a 48-bit value, zero-padded) and the combined string is sliced to exactly 26 characters in the final step.

Validating and decoding both formats

The validator applies a strict regex for each format — the UUID pattern specifically checks for a version digit (1-5) in the expected position and a variant nibble (8, 9, a, or b) in the next group, rather than accepting any 32 hex characters in UUID-shaped groups, which would also match non-compliant "UUID-like" strings. For a recognized ULID, the validator goes further: it decodes the first 10 characters back through the Crockford alphabet into their original 48-bit value and renders it as an ISO date, letting you extract the exact creation timestamp embedded in any ULID you paste in — a capability that has no UUID v4 equivalent, since a v4 UUID intentionally carries no information about when it was created.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Hand this snippet's JavaScript to an AI assistant like Claude and ask it to walk through exactly how the ULID timestamp gets encoded into Crockford Base32 5-bit chunks and why that's different from the 6-bit chunking a typical base64 encoder uses — it's a neat, self-contained bit-manipulation example. It's also a good base to extend: ask for UUID v1 (timestamp-based) or v7 (a newer sortable UUID variant similar in spirit to ULID) generation, a "monotonic ULID" mode that guarantees strictly increasing output even for multiple IDs generated within the same millisecond, or a batch export button that downloads generated IDs as a CSV file.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a UUID v4 and ULID generator and validator in plain HTML, CSS, and JavaScript, no libraries.

Requirements:
- A tab switcher between "UUID v4" and "ULID" generation modes, and a Generate button that produces one identifier using crypto.getRandomValues() (or crypto.randomUUID() where available) — never Math.random() — for the random portion.
- For UUID v4, correctly set the RFC 4122 version nibble (4) and variant bits in the generated bytes before formatting as the standard 8-4-4-4-12 hyphenated hex string.
- For ULID, implement the real algorithm: encode the current millisecond Unix timestamp into the first 48 bits, append 80 bits of cryptographic randomness, and encode the combined 128 bits using Crockford's Base32 alphabet (5 bits per output character) to produce a 26-character sortable string.
- Add a bulk-generation option that produces a user-specified number of identifiers (capped at a reasonable maximum like 100) in the currently selected format, one per line.
- Add a separate validator input where a user can paste any string; use a strict regex to determine whether it's a well-formed UUID (checking the version and variant characters specifically, not just hex-and-dashes shape) or a well-formed ULID (26 Crockford Base32 characters).
- For a valid ULID specifically, decode its first 10 characters back into the embedded 48-bit timestamp and display it as a human-readable ISO date, since this is the ULID's key advantage over a UUID.
- Include a copy-to-clipboard button for the currently generated single value.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Choose UUID v4 or ULIDClick a tab to switch generator mode — the currently displayed identifier regenerates in the newly selected format immediately.
  2. 2
    Click Generate New for a single valueProduces one fresh identifier using real cryptographic randomness from the Web Crypto API.
  3. 3
    Use Copy to grab itCopies the current output value straight to your clipboard.
  4. 4
    Set a bulk count and click GenerateProduces up to 100 identifiers at once in the selected format, one per line, ready to paste into a seed script or test fixture.
  5. 5
    Paste any UUID or ULID into the validatorIt checks the format strictly (including version/variant bits for UUIDs) and reports whether it's valid.
  6. 6
    Read the decoded ULID timestampFor a valid ULID, the validator extracts and displays the exact millisecond timestamp encoded in its first 10 characters as an ISO date.

Real-world uses

Common Use Cases

Seeding test fixtures and database records
Generate a batch of realistic primary-key identifiers for local development seed data or automated test fixtures without writing a script.
Choosing between UUID and ULID for a new schema
Generate a few of each side by side to see the practical difference: ULIDs stay roughly sorted by creation time in a database index, while UUID v4 values are uniformly random and don't.
Debugging an identifier from logs or a support ticket
Paste an ID a user reports seeing into the validator to confirm its format, and for a ULID, instantly see exactly when that record was created without querying the database.
Teaching how UUIDs and ULIDs are actually constructed
Walk through the version and variant bit placement in UUID v4, or the Crockford Base32 timestamp encoding in ULID, using real generated values as concrete examples.
API and integration testing
Quickly generate placeholder resource IDs when manually testing an API endpoint that expects a UUID or ULID path parameter.
Related: Unix Timestamp Converter
See the Unix Timestamp Converter for a related dev pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Math.random() is not specified to be cryptographically secure or unpredictable — in some engines its output can theoretically be predicted from prior outputs. crypto.getRandomValues() (and crypto.randomUUID(), which uses it internally) is backed by the operating system's cryptographically secure random number generator, which is the correct source of randomness for any identifier where uniqueness genuinely matters.

UUID v4 is 128 bits of (mostly) pure randomness with no ordering information — two UUIDs generated a second apart sort in effectively random order relative to each other. A ULID deliberately puts a millisecond timestamp in its first 48 bits, so ULIDs generated later always sort after ones generated earlier as plain strings, which makes them friendlier to database indexes that benefit from roughly-increasing keys.

Crockford's Base32 excludes the letters I, L, O, and U from its alphabet because they are easily confused with 1, 1, 0, and each other when read aloud or handwritten, and U is excluded partly to reduce accidental profanity in generated strings. This makes ULIDs meaningfully easier to transcribe correctly by hand than a base64-encoded identifier.

The validator's regex specifically checks that the version digit (the first character of the third group) is between 1 and 5, and that the variant nibble (the first character of the fourth group) is 8, 9, a, or b, per RFC 4122. A string with correct dash placement but the wrong version or variant character is correctly rejected as not a valid UUID.

The first 10 characters of a ULID encode a 48-bit millisecond Unix timestamp using 5-bit Crockford Base32 chunks. The validator reverses that encoding — looking up each character's 5-bit value and concatenating them back into the original 48-bit number — then constructs a JavaScript Date from that millisecond value to display as an ISO string.

No identifier scheme can mathematically guarantee absolute uniqueness — both UUID v4 and ULID rely on the random portion being large enough that a collision is astronomically unlikely in practice (UUID v4 has 122 random bits; ULID has 80). For virtually all real-world applications this collision probability is negligible, but it is a probabilistic guarantee, not an absolute one.