Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Short UUIDs

On this page
  1. The same UUID, six different lengths
  2. Code
    1. Base64url
    2. Crockford base32
    3. Base58
  3. When to use which
    1. Public-facing URLs → base64url or base58
    2. Storage in databases → don’t shorten
    3. Compact logs → no-hyphens hex
    4. Anywhere case matters → avoid base32 / base58
  4. Don’t try this
    1. Truncating
    2. Encoding as decimal
    3. Lossy “compression”
  5. In the wild
  6. Try the tools

A UUID’s 128 bits don’t change — but the characters used to represent them can. The canonical form (36 chars with hyphens) is the longest. Here’s how to shorten it without losing data, and what each encoding is good for.

The same UUID, six different lengths

EncodingLengthExample
Canonical (hex + hyphens)360e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b
Hex, no hyphens320e6f1b8c2c334f1f9c0b2a3d4e5f6a7b
Crockford base32261WPK0RH1HM7CYJBC1H99TQVCXV
Base58 (Bitcoin alphabet)~22TZkxBfg3xnjaUDH5UQpr3i
Base64url (no padding)22Dm8bjCwzTx-cCyo9Tl9qew
Decimal integer~3919250732086...

All of these encode the same 16 bytes. Pick based on what you need:

Code

Base64url

URL-safe base64 with - and _ instead of + and /, padding stripped. 22 chars per UUID.

function uuidToBase64url(uuid) {
  const hex = uuid.replace(/-/g, "");
  const bytes = new Uint8Array(16);
  for (let i = 0; i < 16; i++) bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
  const b64 = btoa(String.fromCharCode(...bytes));
  return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

function base64urlToUuid(s) {
  const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + "==";
  const binary = atob(b64);
  const hex = Array.from(binary, c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("");
  return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}

Crockford base32

26 chars, case-insensitive, drops I L O U to avoid confusion with 1 1 0 V. Used by ULID and many human-facing IDs.

const ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";

function uuidToCrockford(uuid) {
  const hex = uuid.replace(/-/g, "");
  // 128 bits → 26 chars at 5 bits each (130 bits, top 2 padded)
  const big = BigInt("0x" + hex);
  let n = big, out = "";
  for (let i = 0; i < 26; i++) {
    out = ALPHABET[Number(n & 31n)] + out;
    n >>= 5n;
  }
  return out;
}

Base58

22 chars (variable, but typically 22). Used by Bitcoin, IPFS. Drops 0 O I l for human readability.

const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

function uuidToBase58(uuid) {
  let n = BigInt("0x" + uuid.replace(/-/g, ""));
  let out = "";
  while (n > 0n) {
    out = BASE58[Number(n % 58n)] + out;
    n /= 58n;
  }
  return out.padStart(22, BASE58[0]);
}

For production, use a library like short-uuid (npm) or shortuuid (Python).

When to use which

Public-facing URLs → base64url or base58

https://app.example.com/share/Dm8bjCwzTx-cCyo9Tl9qew

22 chars instead of 36. Cleaner in QR codes, SMS, emails. Easy to type if needed (base58 avoids confusing chars).

Storage in databases → don’t shorten

Store as the native uuid type (16 bytes) regardless of how you display it. The display encoding lives in your application layer; the database stores 16 bytes either way.

Compact logs → no-hyphens hex

{"id":"0e6f1b8c2c334f1f9c0b2a3d4e5f6a7b","event":"login"}

4 characters shorter than canonical, still 100% recognizable as a UUID, no decoding needed.

Anywhere case matters → avoid base32 / base58

0E6F1B8C != 0e6f1b8c   # base64 — case-sensitive
0E6F1B8C == 0e6f1b8c   # hex / base32 — case-insensitive

If your storage or routing layer normalizes case (most databases do this for indexes; some HTTP routers do not), case-sensitive encodings can cause subtle “the URL works but the lookup fails” bugs.

Don’t try this

Truncating

const short = uuid.slice(0, 8);  // ❌ 32 random bits — collisions at ~65K IDs

The first 8 hex chars of a UUID are 32 bits. The birthday-paradox 50% collision threshold drops to about 65,000 IDs. Don’t truncate UUIDs unless you’re prepared to handle collisions explicitly.

If you need a short ID, generate a nanoid at the desired length — it gives you the same security per character as a truncated UUID would, plus a wider alphabet.

Encoding as decimal

Mathematically valid, but a UUID-as-BigInt is ~39 decimal digits — longer than the canonical hex form. Only useful if you have a system that stores 128-bit integers natively (rare).

Lossy “compression”

Some libraries claim to compress UUIDs by stripping fixed bits (the version and variant nibbles). The savings are 6 bits = under 1 character — never worth the round-trip complexity.

In the wild

The pattern across all these: store a stable internal ID (UUID v7 in modern systems), display a compact form in URLs.

Try the tools