How URL Shorteners Generate Short Codes — Encoding Techniques Explained

Services like bit.ly turn a long URL into something like bit.ly/3xK9pQ. The core trick isn't compression — it's encoding. This article explains the two most common approaches, base62 encoding of sequential IDs and hash-based generation, with runnable code for each.

Approach 1: base62 encoding of an auto-increment ID

The simplest and most common design: store the long URL in a database row with an auto-incrementing integer primary key, then encode that integer into base62 (digits 0-9, lowercase a-z, uppercase A-Z — 62 symbols total). Base62 is preferred over base64 because it avoids + and /, which aren't safe in a URL path without encoding.

const ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const BASE = ALPHABET.length; // 62

function encodeBase62(num) {
  if (num === 0) return ALPHABET[0];
  let result = '';
  while (num > 0) {
    result = ALPHABET[num % BASE] + result;
    num = Math.floor(num / BASE);
  }
  return result;
}

function decodeBase62(str) {
  let num = 0;
  for (const char of str) {
    num = num * BASE + ALPHABET.indexOf(char);
  }
  return num;
}

encodeBase62(1);          // 'b'
encodeBase62(1000000);    // '4C92'
encodeBase62(56800235583); // 'ZZZZZZ' — 6 chars covers 56+ billion IDs

decodeBase62('4C92');     // 1000000

Why base62 packs so much into so few characters

Base10 (plain decimal) needs more digits to represent the same number because it only has 10 symbols per position. Base62 has 62 symbols per position, so each character carries roughly log(62)/log(10) ≈ 1.79 times more information than a decimal digit — which is why a 6-character base62 code can represent over 56 billion unique IDs.

  • 4 characters → up to 62⁴ ≈ 14.7 million unique URLs
  • 6 characters → up to 62⁶ ≈ 56.8 billion unique URLs
  • 7 characters → up to 62⁷ ≈ 3.5 trillion unique URLs

Approach 2: hashing the destination URL

An alternative design hashes the original URL (e.g. with MD5 or SHA-256) and takes the first several characters of the hash, re-encoded in base62 or base64url. This avoids needing a sequential counter, but requires collision handling since two different URLs could theoretically produce the same short prefix.

import crypto from 'crypto';

function hashBasedShortCode(longUrl, length = 7) {
  const hash = crypto.createHash('sha256').update(longUrl).digest('base64url');
  return hash.slice(0, length);
}

hashBasedShortCode('https://example.com/very/long/article/path?utm=abc');
// → 'Kx9pQ2z' (deterministic — same URL always produces the same code)

// Collision handling: if the code already maps to a DIFFERENT url in the
// database, append a character and re-hash, or fall back to approach 1

Putting it together: a minimal shortener flow

  1. User submits a long URL to POST /shorten.
  2. Server inserts a new row { id: AUTO_INCREMENT, longUrl } into the database.
  3. Server encodes the new row's id using base62 to get the short code, e.g. 4C92.
  4. Server returns https://short.ly/4C92 to the user.
  5. On GET /4C92, the server decodes the code back to the integer ID, looks up the row, and issues an HTTP 301/302 redirect to the original long URL.

Base62 vs Base64 vs percent-encoding — where they fit

  • Base62 — ideal for generating compact, URL-safe identifiers like short codes, since it needs no percent-encoding at all.
  • Base64 / Base64url — better for encoding arbitrary binary payloads (like JWT segments), not primarily for generating short human-typeable codes.
  • Percent-encoding — a separate concern entirely: it's for safely transmitting characters within an already-formed URL, not for generating the short code itself.

Frequently Asked Questions

How do URL shorteners generate short codes?

Most URL shorteners take an auto-incrementing database ID and encode it in base62 (using 0-9, a-z, A-Z), which produces a short, URL-safe string. A few characters can represent millions of unique IDs because base62 packs more information per character than base10.

Why use base62 instead of base64 for short URL codes?

Base64 includes + and / characters, which are not safe to use directly in a URL path without additional percent-encoding. Base62 uses only letters and digits, so every generated code is already URL-safe with no escaping needed.

Do all URL shorteners use sequential IDs?

No. Some use sequential auto-increment IDs encoded in base62 for simplicity and guaranteed uniqueness. Others use a hash of the destination URL (like the first few characters of an MD5 or SHA-256 hash) combined with collision detection, or a random string generator with a uniqueness check against the database.

Try the Free URL Encoder

Building a redirect or short link feature? Use our free online tool to percent-encode any destination URL or query parameter before storing it.

Related articles