Also available in: Español · Português · Français · العربية
ULID generator and decoder
Sortable, timestamped identifiers — generated monotonically by default, and decoded with the checks most validators skip.
What is a ULID?
A ULID is a 26-character identifier that carries the time it was created. The first 10 characters are a 48-bit count of milliseconds since 1970; the remaining 16 are 80 bits of randomness. Both halves are written in Crockford's base32, an alphabet of the ten digits and twenty-two letters that leaves out I, L, O and U because those are the ones people misread.
The point of putting the clock first is that sorting the text sorts by time. A UUID version 4 is pure randomness, so a table indexed on one scatters its writes across the whole index; identifiers that increase over time keep new rows together. That is the same reasoning behind UUID version 7, which RFC 9562 standardised in 2024 and which is the better choice if you can use it — ULID came first, is not an IETF standard, and is worth knowing mainly because a great deal of software already emits it.
The format also fits in places a UUID does not. It is 26 characters against 36, contains no hyphens, is case-insensitive, and survives being read aloud or typed off a screen better than hex does.
How to use it
- Set how many you need and copy them. Up to a hundred at a time, drawn from your browser's cryptographic random source. Copy one, or copy the whole batch as lines.
- Leave the ordering box ticked unless you know you want it off. It makes identifiers created in the same millisecond count upwards rather than being drawn independently, which is what makes a batch sort into the order it was made.
- Paste any ULID into the second box to read it back. You get the moment it was made in your own time zone, the random half, the canonical spelling, and the same bits written as hex.
Three things other ULID tools get wrong
The first is that a batch of ULIDs is usually not sorted. Twenty-six characters of base32 are only in order if the values behind them increase, and two identifiers made in the same millisecond share a timestamp, so their order is decided by the random half. Two independent random draws are equally likely either way, which makes it a coin flip by construction rather than an occasional glitch — and that is what the measurements show. Over 20,000 calls in a single millisecond the wrong-order rate came out at 49.9, 49.6 and 50.2 per cent for three different random streams, and 49.6 and 50.1 per cent on two runs against the reference implementation for JavaScript in real time. Its monotonic factory puts all of them at zero. Since sortability is the entire reason to prefer this format, the ordering behaviour is on by default here and is a checkbox rather than an assumption.
The second is overflow. Twenty-six base32 characters hold 130 bits, and a ULID is 128, so the first character can only be 0 through 7 — the largest possible ULID is 7ZZZZZZZZZZZZZZZZZZZZZZZZZ. The specification says any attempt to decode a larger one should be rejected by every implementation, precisely to prevent overflow bugs. Trying all thirty-two possible first characters against the reference implementation, its validator returns true for every one while its own decoder throws on twenty-four of them: three quarters of the strings it calls valid are not ULIDs. That case gets its own verdict here rather than being waved through.
The third is transcription. Crockford designed this alphabet so that the excluded letters could be recovered on reading: I and L are decoded as 1, O as 0, and case is ignored. The reference implementation rejects all three and ships a separate repair function you have to call yourself, so a ULID copied off a screenshot fails for no good reason. This tool resolves them and tells you that it did, which is different from resolving them silently.
Honest limits
The timestamp is only as trustworthy as the clock of whatever made the identifier. A ULID says when the machine that generated it thought it was; on a device with a wrong clock, or one that stepped backwards over a leap second or an NTP correction, the value is wrong and nothing in the format records that. Sorting is a convenience, not an audit trail.
The random half is not a signature. Anyone can generate an identifier with any timestamp they like — the format has no secret and no checksum, so a ULID proves nothing about who made it or when. Treat one as a name, never as evidence.
The ULID to UUID conversion every tool offers is exact but the result is not a UUID. It is the same 128 bits written as hex, and a UUID reserves four bits for a version number and two for a variant, which a ULID's random field knows nothing about. About one ULID in sixty-four happens to land on values that would pass as a version 4 UUID; the rest are hex strings shaped like a UUID that no conforming parser will accept as one. This page shows the hex and says which case yours is.
Finally, monotonic ordering is per generator, not global. Two servers generating in the same millisecond will interleave however their random halves fall, and nothing coordinates them. Within one browser tab, one process or one connection pool, the order holds; across machines it does not.
Why is it free?
Everything happens in your browser. The random bits come from your own cryptographic random source, the clock is your clock, and no identifier is ever sent anywhere — which matters more here than usual, since an identifier a server has seen is not really yours to use as a secret token.
There is no account, no limit and no watermark, because there is no server cost to recover.