What this tool does
A ULID (Universally Unique Lexicographically Sortable Identifier) is 128 bits: a 48-bit Unix time in milliseconds followed by 80 random bits, written as 26 characters of Crockford's Base32 (the digits and the letters A–Z without I, L, O and U). The first 10 characters are the time and the last 16 the randomness, so ULIDs sort in creation order as plain text. Ten Base32 characters hold 50 bits, so the first character is at most 7 and the largest ULID is 7ZZZZZZZZZZZZZZZZZZZZZZZZZ, in the year 10889. With Monotonic on (the default), IDs made in the same millisecond reuse its time and add one to the previous random part, so a batch is strictly increasing; if that ever overflowed, generation fails as the spec requires. The decoder accepts lowercase, reads I and L as 1 and O as 0 as Crockford's Base32 allows (and warns, because strict parsers reject them), and shows the time in UTC and your local time zone, the random part in Base32 and hex, and the same 16 bytes as a UUID. Pasting a UUID v7 converts it to its ULID spelling with a meaningful time. NanoIDs use the URL-safe alphabet A–Z a–z 0–9 _ - and 21 characters by default (126 random bits), or any alphabet of 2 to 256 characters and any length up to 256. Each character is picked with nanoid's mask-and-reject method, so no character is more likely than another.
Example input and output
01ARZ3NDEKTSV4RRFFQ69G5FAVValid ULID.
Created (UTC) 2016-07-30T23:54:10.259Z
Unix ms 1469922850259
Time part 01ARZ3NDEK (48 bits)
Random part TSV4RRFFQ69G5FAV (80 bits)
Random (hex) d6764c61efb99302bd5b
As UUID 01563e3a-b5d3-d676-4c61-efb99302bd5bThis is the example ULID from the spec. The ulid npm package and python-ulid decode it to the same time and bytes.
Time 1508808576371 (2017-10-24T01:29:36.371Z), first random part ACTAV9WEVGEMMVRZ01BX5ZZKBKACTAV9WEVGEMMVRZ
01BX5ZZKBKACTAV9WEVGEMMVS0
01BX5ZZKBKACTAV9WEVGEMMVS1The time part 01BX5ZZKBK stays the same and the random part counts up by one (Z rolls over to 0 and carries); the first two lines are the spec's own monotonic example. With Monotonic off, each ID gets fresh random bits, so IDs from the same millisecond sort in random order.
URL-safe alphabet (64 characters), 21 characters
URL-safe alphabet (64 characters), 8 characters21 characters: 126 random bits, ~149 billion years (about 1.31 quintillion IDs)
8 characters: 48 random bits, ~99 days (about 2.38 million IDs)Each figure is the point where the chance of at least one duplicate reaches 1%. The default matches nanoid's own collision calculator; shortening the ID to 8 characters makes a clash likely within months.
Common errors and fixes
- Character 26 is “U”. Crockford's Base32 leaves out U (as well as I, L and O), so no ULID contains it.
- The value is not a ULID, or a character was mistyped. ULIDs only use 0–9 and A–Z without I, L, O and U. If you typed it by hand, check letters that look alike, such as U and V.
- A ULID has exactly 26 characters (10 for the time, 16 random); this has 25.
- It was cut off or has extra characters, often a quote, a bracket or a space picked up when copying from a log. Copy it again; 32 hex digits or the 8-4-4-4-12 form means it is a UUID, which the decoder also accepts.
- The first character is “8”, but it can be at most 7.
- The 48-bit time would overflow: ten Base32 characters hold 50 bits, so the top two must be zero. The value was not made by a ULID generator, or its first character was changed.
- Character 11 is “-”, which is not in Crockford's Base32
- ULIDs have no hyphens. Remove them, or if it is a UUID, paste all 32 hex digits so it can be converted.
- Decoded, but not written as a ULID should be (I, L or O)
- Crockford's Base32 reads I and L as 1 and O as 0, so the tool decodes it and shows the canonical spelling, but strict parsers such as the ulid npm package's decodeTime and python-ulid reject the original. Store and compare the canonical form.
- Repeated characters: “a”. Each must appear once, or it comes up more often than the others.
- A custom NanoID alphabet must list each character once; a repeated one would be picked twice as often and make IDs easier to guess. Remove the duplicates. The alphabet needs 2 to 256 characters.
Common use cases
- Primary keys that sort by creation time, for B-tree indexes, logs and event streams
- Reading the creation time out of a ULID found in a log, URL or database row
- Short URL-safe IDs for links, invites, file names and front-end keys
- Choosing a NanoID length that stays collision-safe at your write rate
- Bulk test IDs for fixtures and seed data
Privacy and security notes
- IDs are generated in this browser tab from crypto.getRandomValues, the browser's cryptographically secure random number generator, and nothing is sent to DevPrix or stored. Neither kind of ID is a password or an access token: if one must be unguessable, keep plenty of random bits (a ULID has 80, the default NanoID 126) and still check permissions on the server.
- A ULID reveals when it was created, to the millisecond. Don't use ULIDs where that timestamp is private, such as account IDs that would show sign-up times; use a NanoID or a UUID v4 instead.
- Share copies a link that carries only the ULID (or UUID) you pasted into Decode, after the # in the URL; generated IDs are never put in the link. Browsers do not send that part to servers, but anyone you give the link to can read it.
Frequently asked questions
ULID or UUID v7?
Both put a 48-bit Unix millisecond time first, so both sort by creation time. UUID v7 is standardised in RFC 9562, has 74 random (or counter) bits because six go to the version and variant, and fits a native uuid column; a ULID has 80 random bits and a shorter 26-character text form. Pick UUID v7 if your database or framework has UUID support, a ULID if you want compact sortable strings. Both are 16 bytes, so this tool can show either one in the other's notation.
What does monotonic mean, and should I turn it off?
When several ULIDs are made in the same millisecond, their time parts are equal, so by default their order would be random. Monotonic mode adds one to the previous random part instead, so IDs made in sequence also sort in sequence. Keep it on unless you don't want consecutive IDs to be guessable from each other, since a monotonic ID reveals its neighbour.
How is the NanoID collision time calculated?
With N = alphabet size ^ length possible IDs, the chance of at least one duplicate among n random IDs is about 1 − e^(−n(n−1)/2N) (the birthday problem). Setting that to 1% gives n ≈ ½ + √(¼ + 2N·ln(1/0.99)), and the time is n divided by your rate. For realistic sizes this equals the √(2N·ln(1/(1−p))) used by nanoid's collision calculator; for tiny ID spaces the tool multiplies out the exact probability instead.
Why not pick NanoID characters with random % alphabet.length?
A random byte has 256 values. With a 10-character alphabet, 256 isn't a multiple of 10, so % would make 0–5 slightly more likely than 6–9. Like nanoid, the tool masks each byte to the smallest power of two that covers the alphabet (15 for ten characters) and throws away values past the end, so every character is equally likely.