ULID Generator

ULIDs sort lexicographically by time, like UUID v7. They are not UUIDs: no hyphens, Crockford alphabet (no I, L, O, or U).

By Cobra · Last updated

Crockford time-ordered IDs

ULIDs are 128-bit IDs: 48 bits of timestamp plus 80 bits of randomness, encoded as 26 Crockford Base32 characters. Lexicographic sort matches time order, which helps for log filenames and DB keys that want roughly increasing inserts without exposing a sequence number.

This page mints ULIDs with Web Crypto randomness in your browser. Optional lowercase output matches ecosystems that prefer that style.

Worked example: batches and monotonic mode

A ULID looks like 01J8H8K0Y0ABCDEFGHJKLMNPQR (shape illustrative). The leading characters move slowly as time advances; the trailing characters jump randomly per ID.

Generating a batch gives one ID per line for paste into fixtures. Monotonic mode (when enabled) bumps randomness within the same millisecond so IDs stay ordered under bursty creates.

Limits

ULIDs embed creation time, which can leak timing metadata. Prefer opaque NanoIDs when time leakage matters. Clock rollback can produce IDs that sort oddly unless your library handles monotonicity. This page is not a distributed ID service.

Storage and indexing notes

Store ULIDs as 26-character strings or as 16 bytes if your DB has a binary ULID type. String storage is simple and sorts correctly as text for Crockford encodings. Binary storage saves space but needs consistent endianness in every writer.

Worked example: decoding the 26 characters

A ULID like 01ARZ3NDEKTSV4RRFFQ69G5FAV is 26 characters of Crockford Base32. The first 10 characters encode a 48-bit millisecond timestamp and the last 16 encode 80 random bits. Because the time comes first, sorting ULIDs as plain strings sorts them by creation time to the millisecond.

Pitfalls

Create ULIDs in JavaScript, Python and Go

Each snippet makes a ULID, decodes its timestamp, and shows the monotonic or parse helper the library offers.

JavaScript: ulid

import { ulid, monotonicFactory, decodeTime } from "ulid"; // npm i ulid

const id = ulid();
console.log(id, new Date(decodeTime(id)).toISOString());

// Monotonic: IDs made in the same millisecond still sort in creation order
const next = monotonicFactory();
console.log(next(), next(), next());

Python: python-ulid

from ulid import ULID  # pip install python-ulid

u = ULID()
print(str(u), u.datetime)    # 26-character string, UTC timestamp
print(u.to_uuid())           # same 128 bits as a UUID

parsed = ULID.from_str(str(u))
print(parsed.timestamp)      # Unix seconds as a float

Go: github.com/oklog/ulid/v2

package main

import (
	"fmt"

	"github.com/oklog/ulid/v2" // go get github.com/oklog/ulid/v2
)

func main() {
	id := ulid.Make() // monotonic within a millisecond, safe for concurrent use
	fmt.Println(id.String(), ulid.Time(id.Time()).UTC())

	parsed, err := ulid.Parse(id.String())
	if err != nil {
		panic(err)
	}
	fmt.Println(parsed.Time() == id.Time()) // true
}

Each snippet was run on October 14, 2026 with ulid 3.0.2, python-ulid 4.0.1 and oklog/ulid v2.1.2.

ULID spec and sources

FAQ

What is a ULID?

A 128-bit time-ordered ID encoded as 26 Crockford Base32 characters. It sorts by time and needs no central sequence server.

Does this upload ULIDs?

No. Generation is local only.

ULID vs UUID v7?

Both are time-ordered 128-bit IDs. UUID v7 uses RFC 9562 UUID layout. ULID uses Crockford Base32 strings. Pick the ecosystem your stack already parses.

Why Crockford Base32?

It avoids lookalike characters and stays case-insensitive in spirit, which reduces transcription errors.

ULID or UUID v7?

Both are time-ordered with 48-bit millisecond timestamps. UUID v7 fits UUID columns and tooling; ULID is shorter as text (26 vs 36 characters).

Can I convert a ULID to a UUID?

Both are 128 bits, so a ULID can be stored in a UUID column as bytes, but the result will not have valid UUID version bits.