Base62 Encoding Explained: Short URLs and Short IDs from Big Integers
How Base62 turns big integer IDs into short URL-safe strings. Why short-link services pick 0-9a-zA-Z, how it beats Base64 in a URL, with a worked example.
Base62 Encoding Explained: Short URLs and Short IDs from Big Integers
Every short link you have ever clicked is a small math problem. A service stores a long destination behind a row in a database, that row has a numeric key, and the job is to print that number as the shortest string that can sit in a URL without breaking. Base62 is the answer almost everyone reaches for. It uses the 62 characters that no URL parser argues about: the digits 0 through 9, the uppercase letters A through Z, and the lowercase letters a through z. Nothing else. No plus sign, no slash, no equals padding.
This post walks through what Base62 actually does, why it wins over Base64 for links, and how a giant integer ID collapses into a handful of characters. If you want to follow along while you read, keep the Base62 encoder and decoder open in another tab and paste in your own numbers.
What Base62 is, in one paragraph
Base62 is positional notation, exactly like the decimal system you learned in school, except it has 62 distinct digits instead of 10. In decimal, when you run out of single digits at 9, you roll over to 10. In Base62 you have 62 symbols before you roll over, so the count goes 0, 1, 2 ... 9, A, B ... Z, a, b ... z, and only then does it become 10. The letter A carries the value 10, Z is 35, lowercase a is 36, and z is the last single digit at value 61. That ordering, digits then uppercase then lowercase, is the common convention. Some libraries flip the cases, which is the single most frequent source of "why does my decoder disagree" bugs.
Here is a clean character set to anchor the idea, and notice it is exactly 62 characters long with no symbols that mean anything special in a URL:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
A worked example: turning a number into a short string
Take the number 125. To convert it to Base62, you divide by 62 and track the remainders, lowest place last, the same way you would convert to binary or hexadecimal.
- 125 divided by 62 is 2, with a remainder of 1.
- That quotient, 2, is less than 62, so it is the final high digit: 2.
Read the digits high to low and you get 2 then 1, so 125 encodes to 21. Decoding reverses the arithmetic: 21 means 2 times 62 plus 1, which is 2 × 62 + 1 = 125. The round trip is exact, and it stays exact no matter how large the number grows.
That last point matters more than it looks. JavaScript's normal numbers stop being safe above 2^53, but a 64-bit database ID can run far past that. A real encoder uses BigInt arithmetic so the division never loses precision, which is why a value like 9,876,543,210 has a stable short form that always decodes back to the same integer.
Why Base62 beats Base64 for URLs
Base64 is the encoding most developers meet first, and it is genuinely faster: it packs 6 bits per character with simple bit shifting, no division required. But its alphabet includes +, /, and the = padding character. All three are special inside a URL path or query string, which means a Base64 value usually has to be percent-encoded before it can travel, turning a clean a+b/c= into the noisy a%2Bb%2Fc%3D. The moment a link gets copied through a chat app or an email client, those escapes are where things break.
Base62 removes exactly those three troublemakers. What is left is 62 characters that every URL parser passes through untouched, so the string survives copy-paste, redirects, and logging with no escaping at all. The trade-off is honest: because 62 is not a power of two, Base62 needs real division instead of bit shifting, so the output runs a few percent longer than Base64 for the same value. For a short link that lives in the address bar, URL-safety beats those few characters every time. If you are working the other side of that trade and need raw byte packing, the Base64 encoder is the right tool, and it handles the URL-safe variant too.
Why short-link services land on Base62
A short link is a mapping from a tiny public key to a long stored destination. The stored key is almost always a sequential integer, because auto-increment primary keys are cheap and collision-free. The shortest URL-safe way to print a sequential integer is Base62, and the growth curve is gentle: a 7-character Base62 slug covers 62^7, which is about 3.5 trillion links. That is why you see codes shaped like /3dPq9Zx. Early IDs encode to two or three characters, and the slug grows only one character at a time as the table fills.
There is a quiet bonus here too. Encoding the key instead of exposing the raw integer hides how many rows you have. A route like /article/4815162342 advertises your scale and invites someone to walk the IDs; /article/5Bz3kQ gives nothing away while still decoding back to the exact row when you need to debug it.
When Base58 is the better pick
Base62 is built for machines generating and consuming codes. When a human has to read a string aloud or type it by hand, Base58 is often the smarter choice, because it drops the four characters people misread: 0, O, I, and l. That is why Bitcoin addresses and IPFS hashes use it. The rule of thumb: pick Base62 when software both creates and reads the string, and reach for Base58 when a person is in the loop. If you want to compare the two side by side, the Base32 and Base58 encoder sits right next to this one in the toolbox.
How I actually use it
I reach for Base62 most often when I am debugging someone else's IDs. Last month an upstream API was handing me codes like 4kP9zQ and my own decoder disagreed on one value, which usually means an alphabet mismatch. I pasted their string into decode mode and my integer into encode mode, then compared both directions against the standard ordering. The decode came back as a clean number and re-encoded identically, which told me the format was fine and the bug was on my side, in a route that had stripped a leading character. Five minutes, no scratch script, no guessing. That is the whole appeal: the encoding is simple enough that the tool just confirms what the math says.
One habit worth keeping: Base62 is an encoding, not encryption. Anyone can decode a Base62 string back to the original number or text, so it is for compactness and URL-safety, never for hiding a token or a secret. If you need privacy, reach for the copy button instead of the shareable link, because the link writes your input into the query string where a recipient's server log will record it.
The short version
Base62 is positional counting with 62 digits, drawn from 0-9A-Za-z, chosen so the result drops straight into a URL with no escaping. It turns big integer IDs into short, stable codes that round-trip exactly thanks to BigInt division, it beats Base64 wherever the URL itself is the channel, and it gives way to Base58 only when a human has to handle the string. Open the Base62 encoder and decoder, paste in a row ID, and watch a twelve-digit number become a six-character slug.
Made by Toolora · Updated 2026-06-13