PureDevTools

CUID2 Generator

Generate collision-resistant unique IDs that always start with a letter — safe everywhere

All processing happens in your browser. No data is sent to any server.

Generate CUID2 Identifiers

Default 24. Longer = less collision risk.

CUID2 Properties

Collision-Resistant

Uses SHA-256 hash of timestamp + counter + randomness. Not sequential — no information leaks.

Not Predictable

Counter-based entropy source makes brute-force enumeration infeasible even if some inputs are known.

Safe for URLs

Lowercase alphanumeric only. Always starts with a letter — safe as HTML IDs, class names, and URL segments.

Not Monotonic

Unlike ULID/UUID v7, CUID2 has no timestamp prefix. Best when you don't need sort-by-creation.

CUID2 vs UUID v4 vs ULID

FeatureCUID2UUID v4ULID
Length243626
URL-safeYesWith careYes
Time-orderedNoNoYes
Always letter-startYesNoNo
StandardCommunityRFC 9562Community

You need a unique identifier that is safe for public URLs, works as an HTML element ID, never starts with a number, and reveals absolutely nothing about when or how many records have been created. UUID v4 starts with a hex digit, ULID exposes creation time, and auto-increment is out of the question for security-sensitive contexts. CUID2 was designed precisely for this scenario.

What Is CUID2?

CUID2 is the second generation of the Collision-Resistant Unique IDentifier format, developed by Eric Elliott and the ParallelDrive team. CUID2 addresses weaknesses in the original CUID1 format — specifically, CUID1’s sequential counter made IDs partially predictable.

CUID2 generates identifiers that are:

A typical CUID2 looks like: clh3ux4f90001vkge5gq2g77d

Why “Always Starts With a Letter” Matters

Most ID formats can start with a digit. This is a problem in several contexts:

CUID2 solves this by always placing a random lowercase letter as the first character, making IDs safe for use everywhere without any special handling.

How CUID2 Generation Works

CUID2 uses a deterministic hash construction rather than pure randomness:

  1. Timestamp component: The current Unix timestamp in milliseconds, encoded in base36.
  2. Counter component: A session counter, incremented on each call and encoded in base36. This ensures uniqueness when multiple IDs are generated within the same millisecond.
  3. Fingerprint component: A value derived from session-specific data (browser user agent, runtime properties). This differentiates IDs generated by different clients at the same time.
  4. Random component: 32 bytes from crypto.getRandomValues().
  5. SHA-256 hash: All components are concatenated and hashed with SHA-256. The hash output is encoded in base36 and truncated to the desired length.
  6. Prefix: A random lowercase letter is prepended.

The SHA-256 hash ensures that the output has no statistical correlation to any of the inputs. Even if two clients generate IDs with nearly identical inputs, the outputs are computationally indistinguishable.

CUID2 vs UUID v4 vs ULID

FeatureCUID2UUID v4ULID
Default length243626
Alphabeta-z, 0-9hex + hyphensCrockford Base32
Starts with letterAlwaysNeverSometimes
Time-orderedNoNoYes
Timestamp leakageNoNoYes
URL-safeYesWith encodingYes
StandardCommunityRFC 9562Community
Hash-basedYesNoNo

When to Use CUID2

Public-facing resource identifiers: When an ID appears in a URL or API response, you may not want it to reveal creation time or record count. CUID2 exposes neither — the SHA-256 hash obscures all structural information.

HTML element IDs: CUID2 is guaranteed safe as an id attribute value — lowercase alphanumeric, starts with a letter, no special characters.

Short codes with safety: With a length of 10, CUID2 provides adequate collision resistance for databases with up to tens of millions of records.

Security-sensitive contexts: When you need an identifier that resists reverse-engineering, CUID2’s hash construction provides preimage resistance — knowing the output reveals nothing about the inputs.

Generating CUID2 in Code

// npm install @paralleldrive/cuid2
import { createId } from '@paralleldrive/cuid2';

// Default length (24)
const id = createId();
// "clh3ux4f90001vkge5gq2g77d"

// Custom length
import { init } from '@paralleldrive/cuid2';
const cuid2 = init({ length: 10 });
const shortId = cuid2();
// "clh3ux4f90"

// Validation
import { isCuid } from '@paralleldrive/cuid2';
isCuid("clh3ux4f90001vkge5gq2g77d"); // true
# pip install cuid2
from cuid2 import cuid_wrapper

cuid = cuid_wrapper()
id = cuid()
# "clh3ux4f90001vkge5gq2g77d"
// TypeScript with validation
import { createId, isCuid } from '@paralleldrive/cuid2';

interface Record {
  id: string;
  name: string;
}

const record: Record = {
  id: createId(),
  name: "Example",
};

Collision Resistance at Scale

The mathematical collision resistance of CUID2 depends on the length:

LengthSafe generation count (1% collision probability)
10~1 billion
16~4 trillion
24 (default)~4.2 × 10^17 (420 quadrillion)
32~7.3 × 10^23

For a database with 100 million records, length 10 is mathematically sufficient. The default length of 24 provides an enormous safety margin suitable for any realistic scale.

What CUID2 Does Not Solve

CUID2 is not suitable when you need:

Privacy

All CUID2 generation runs in your browser using the Web Crypto API (crypto.getRandomValues() and crypto.subtle.digest()). No data is sent to any server. The fingerprint component uses only client-side information that never leaves your browser.

Frequently Asked Questions

Is CUID2 better than UUID v4? It depends on your requirements. CUID2 is better when you need: always-starts-with-a-letter, URL-safe without encoding, or configurable length. UUID v4 is better when you need: database-native support (UUID type), RFC standardization, or time-ordering (UUID v7).

Can CUID2 collide? Collisions are theoretically possible but practically negligible at default length 24. The birthday paradox probability for 24-character base36 strings is astronomically small — you would need to generate more IDs than atoms in the observable universe before collision became a concern.

Why does CUID2 use a hash instead of raw random bytes? Raw randomness alone does not prevent the birthday paradox as efficiently as a well-constructed hash that combines multiple entropy sources. The counter component ensures uniqueness even under identical conditions, and the hash prevents statistical correlation between sequential IDs.

Is CUID2 compatible with the original CUID? No. CUID2 is a completely new format and not backward compatible with CUID1. CUID1 IDs start with c followed by a timestamp-based prefix. CUID2 IDs start with a random letter and have no recognizable structure.

Related Tools

More Code & Config Generators