URL-Safe UUIDs: Compressing 36 Characters Into 22

    26 February 2024
    9 min read
    Technical explainer
    Tutorial
    uuid
    performance
    best-practices

    UUIDs are everywhere — but their default string format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) takes up 36 characters, which can be verbose in URLs, QR codes, and user-facing identifiers.

    So… what if we could make them shorter — say, 22 characters — while keeping them globally unique?

    Good news: we can.

    Let’s explore how to safely compress UUIDs using Base64 URL-safe encoding, and when (and how) you should use them.


    📏 Why Are UUIDs 36 Characters Long?

    The canonical UUID string format looks like this:

    code
    550e8400-e29b-41d4-a716-446655440000
    • It contains 32 hex characters
    • Plus 4 hyphens
    • Total: 36 characters

    Internally, a UUID is actually 128 bits (or 16 bytes). The string version is just one possible representation.


    🎯 Our Goal: 22 Characters

    Using Base64 encoding, we can take that 16-byte binary and convert it to a much more compact form.

    • Base64 encodes 3 bytes into 4 characters
    • 16 bytes → 22 characters + 2 padding =

    We’ll use Base64 URL-safe mode (with - and _ instead of + and /).

    By stripping the padding, we get a compact, safe, and unique 22-character string.


    🧪 Encoding Example in Python

    python
    import uuid
    import base64
    
    def uuid_to_short(uuid_obj):
        return base64.urlsafe_b64encode(uuid_obj.bytes).rstrip(b'=').decode('ascii')
    
    def short_to_uuid(short_str):
        padded = short_str + '=='
        return uuid.UUID(bytes=base64.urlsafe_b64decode(padded))
    
    # Example usage
    u = uuid.uuid4()
    short = uuid_to_short(u)
    print("UUID:", u)
    print("Short:", short)
    
    # Reverse it
    original = short_to_uuid(short)
    print("Recovered UUID:", original)

    📦 Go (Golang) Example

    go
    package main
    
    import (
        "encoding/base64"
        "fmt"
        "github.com/google/uuid"
        "strings"
    )
    
    func main() {
        u := uuid.New()
        encoded := base64.URLEncoding.EncodeToString(u[:])
        short := strings.TrimRight(encoded, "=")
        fmt.Println("Short UUID:", short)
    
        // Decode back
        padded := short + strings.Repeat("=", (4 - len(short)%4) % 4)
        decoded, _ := base64.URLEncoding.DecodeString(padded)
        recovered, _ := uuid.FromBytes(decoded)
        fmt.Println("Recovered UUID:", recovered)
    }

    🧑‍💻 JavaScript (Node.js) Example

    js
    const { v4: uuidv4, parse, stringify } = require('uuid');
    
    function uuidToShort(u) {
        const bytes = parse(u);
        const base64 = Buffer.from(bytes).toString('base64url');
        return base64;
    }
    
    function shortToUuid(s) {
        const padded = s.padEnd(24, '=');
        const bytes = Buffer.from(padded, 'base64url');
        return stringify(bytes);
    }
    
    const u = uuidv4();
    const short = uuidToShort(u);
    const recovered = shortToUuid(short);
    
    console.log("UUID:", u);
    console.log("Short:", short);
    console.log("Recovered:", recovered);

    🧠 Why This Works

    • UUIDs are exactly 128 bits
    • Base64 encoding is deterministic and reversible
    • The URL-safe variant replaces + with - and / with _
    • Padding == can be dropped safely and restored when decoding

    This means we can safely convert UUIDs to shorter, more portable strings.


    🛡️ Is It Still Unique?

    Yes!

    • No entropy is lost — you’re encoding the full 16-byte UUID
    • It’s just a different representation, like hex() vs .bytes
    • UUID collisions remain astronomically unlikely (~1 in 2^122)

    🔐 Security and Safety Considerations

    • These short UUIDs are not encrypted or obfuscated
    • Anyone can decode them back to the full UUID
    • Do not embed sensitive data (use JWTs or signed tokens for that)

    If you need cryptographic integrity, consider:

    • JWTs with claims
    • Signed UUIDs (e.g. HMAC(uuid))
    • UUIDv5 with secret namespace

    📘 Use Cases

    • Short URLs (example.com/r/22charid)
    • URL-safe file names
    • Embed in QR codes or slugs
    • Compact API keys or tokens
    • Visual UIs where UUIDs are user-facing

    🚫 Don’t Do This

    • Don’t truncate UUIDs manually (e.g. uuid[:8]) — it destroys uniqueness
    • Don’t use regular Base64 with + and / in URLs — not safe!
    • Don’t forget to add padding back when decoding (some libs fail silently)

    🧪 Benchmarking Storage and Display

    FormatLengthURL-safeReadable
    UUIDv4 (canonical)36❌✅
    UUID (hex only)32✅✅
    Base64 (URL-safe)22✅✅
    Base58 (optional)~22✅✅

    🔄 Round Trip Consistency

    Always test:

    text
    UUID → compressed → decompressed → UUID

    If you end up with a different UUID at the end, your encoding logic is broken. Stick to well-tested libraries and watch for issues with padding, bytes vs strings, or endianness.


    Final Thoughts

    If you want shorter UUIDs without losing any uniqueness, Base64 URL-safe encoding is a fantastic solution.

    You get:

    • Compact 22-character identifiers
    • Perfect reversibility
    • Full UUID compatibility
    • Safe usage in URLs, HTML, filenames, and API paths

    So go ahead — compress those UUIDs. Your URLs (and your users) will thank you.

    📦 36 → 22: Done right.

    Generate Your Own UUIDs

    Ready to put this knowledge into practice? Try our UUID generators:

    Summary

    This article explains how to transform standard UUIDs into compact, URL-safe formats using Base64 encoding. Includes code examples, best practices, and guidance for safely shortening UUIDs without compromising uniqueness.

    TLDR;

    Standard UUIDs are 36 characters long — but can be safely encoded into 22-character URL-safe strings using Base64.

    Key takeaways:

    • Convert UUIDs to 16-byte binary and encode using Base64 URL-safe mode
    • Strip padding (=) to get a consistent 22-character representation
    • Decoding must account for padding restoration

    Great for short URLs, compact tokens, and readable links — with no loss of uniqueness or integrity.