Back to blog
DeveloperPublished 2026-07-147 min read

How URL Shorteners Generate Short Codes (Base62 Explained)

Every short link boils down to the same lookup: a code, a database row, a destination URL. The interesting engineering problem isn't the redirect — it's how do url shorteners work under the hood to turn a growing table of millions of rows into codes that stay short, forever, without ever colliding. The answer, in almost every production shortener, is a specific number-encoding scheme called Base62.

The Core Problem: Millions of Rows, Four Characters

Say you're building a shortener and you've just inserted your ten-millionth link. You need a code for it — something that fits in a URL path, ideally under eight characters, and is guaranteed not to already belong to a different link.

The naive options fail fast:

  • Use the row's decimal ID directly. cut.bd/10000000 isn't short — an 8-digit number is exactly as long as an 8-character code, with none of the compactness a real short code needs.
  • Hash the destination URL. A raw MD5 or SHA hash is 32+ hex characters — you'd have to truncate it so aggressively that collisions become common, and now you need a fallback anyway.
  • Just increment a counter and use it as-is. This works for uniqueness, but a base-10 counter burns through characters fast: you need 7 digits just to represent 10 million, and every additional order of magnitude adds another character.

What you actually want is a way to represent that same growing integer in as few characters as possible, using every character available to you in a URL path. That's exactly what Base62 does.

Diagram showing Base62 conversion: the database ID 12345678 is repeatedly divided by 62, and the remainders read in reverse spell the short code PNFQ

Base62: The Encoding Almost Every Shortener Uses

Base62 encodes a number using 62 symbols instead of the 10 digits decimal uses: 0-9, a-z, and A-Z. More symbols per digit means each additional character represents a much bigger jump in capacity — the same reason hexadecimal (base 16) writes large numbers more compactly than decimal.

Why 62 specifically, and not something rounder like 64? Base64 is the more familiar encoding, but it adds +, /, and = to the alphabet — none of which are safe to drop directly into a URL path without escaping. Base62 sticks to only letters and digits, so the output is guaranteed to be URL-safe with zero encoding overhead, at the cost of two symbols' worth of density. That trade is worth it for every shortener that doesn't want to think about percent-encoding edge cases.

Here's the actual conversion, in the form most shorteners implement it:

const ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

function toBase62(id) {
  let code = ""
  while (id > 0) {
    code = ALPHABET[id % 62] + code
    id = Math.floor(id / 62)
  }
  return code || "0"
}

toBase62(12345678)  // "PNFQ"

An 8-digit database ID becomes a 4-character code. That's the entire trick — no randomness, no hashing, just repeatedly dividing by 62 and reading off the remainders, the same way you'd convert a number to binary by dividing by 2.

The capacity math is what makes this practical at scale:

  • 6 characters → 62⁶ ≈ 56.8 billion possible codes
  • 7 characters → 62⁷ ≈ 3.5 trillion possible codes

Most shorteners never need to hand out a 7-character code in the codebase's lifetime — 6 characters alone comfortably outlasts almost any product's realistic link volume.

Where the Number Comes From

Base62 encoding needs a number to encode, and there are two common sources for it.

Auto-incrementing database ID. Every new link gets the database's next sequential ID, and that ID gets Base62-encoded into the short code. This is simple and guarantees uniqueness for free — the database already enforces that IDs never repeat. The downside is predictability: if cut.bd/PNFQ exists, then cut.bd/PNFR (the next ID) probably does too, which makes it possible to enumerate a company's links just by incrementing a code. Shorteners that care about this either add a deterministic shuffle step after encoding, or skip sequential IDs entirely.

Random generation with a collision check. Instead of encoding a sequential number, generate a random string of Base62 characters directly, check whether it already exists in the database, and regenerate if it does. This produces unpredictable codes with no enumeration risk, at the cost of an extra database lookup per link creation — usually negligible, since collisions are rare enough that the check almost always passes on the first try.

The Collision Math Behind "Rare Enough"

"Rare enough" is a specific, calculable number, not a guess. With 7-character random codes drawn from 3.5 trillion possibilities, the birthday-paradox threshold — the point where you'd expect a roughly 50% chance of any collision ever occurring — sits around the square root of that space, or about 1.9 million codes generated. Most products won't create anywhere near that many links across their entire lifetime, which is why "generate randomly, retry on collision" is a completely reasonable production strategy rather than a shortcut. The retry logic is still required, though — "extremely unlikely" is not the same as "impossible," and a shortener that skips the uniqueness check on the assumption that a collision "won't happen" will eventually silently overwrite someone's link.

Custom Aliases Are a Third Path, Not a Special Case

When a user picks their own alias instead of accepting a generated one — the custom vs. generic short URL choice — no encoding algorithm runs at all. The system just checks the requested string against the same uniqueness constraint that auto-generated codes use, and either accepts it or rejects it as taken. Custom aliases don't need their own code path; they're just user input validated against the same table.

Why This Matters Beyond Trivia

For anyone building against a shortener's API rather than just using one, a few practical consequences fall out of how the encoding works:

  • Short codes are case-sensitive. Base62 relies on uppercase and lowercase being distinct symbols — PNFQ and pnfq are different codes pointing at different links. Never normalize a short code's casing before a database lookup.
  • The short_code column needs a unique index, not just a regular one — it's the only thing standing between "rare collision" and "silently broken link."
  • Bulk link creation should expect occasional retries. An API that creates thousands of links per request should treat a collision on generation as a normal, handled case, not an error to surface to the caller.

Where Cut.bd Fits

Cut.bd generates short codes with Base62 encoding by default on every plan, and lets you swap in a custom alias per link with the same uniqueness check running underneath either path — no separate "vanity URL" system to maintain. If you're still working out whether a shortener is the right tool at all, our guide to how URL shorteners work covers the fundamentals first.

Frequently Asked Questions

Why 62 characters instead of 26 or 36? More symbols per character means shorter codes for the same capacity. 26 (letters only) or 36 (letters + digits, one case) both work, but need more characters to reach the same number of possible codes — Base62's 62 symbols is the largest alphabet that stays URL-safe without escaping.

Can two different long URLs end up with the same short code? Only if the system has a bug. The short code is a unique key — the database enforces that no two rows share one, whether the code came from encoding a sequential ID or from random generation with a collision check.

Is Base62 encoding secure? Not on its own. Sequential Base62 codes are guessable by design — encoding is about compactness, not obscurity. If unpredictability matters (private links, for example), random generation is the right choice, not sequential encoding.

How many links can a 6-character Base62 code support? 62⁶, or about 56.8 billion — far beyond what nearly any shortener will generate before needing to add a 7th character, which multiplies capacity by another 62x.

Try Cut.bd's link shortener — free, no account required.

Shorten a link