Why bases matter beyond binary/decimal/hex
The three bases every developer knows are decimal (10), binary (2), and hex (16). They appear in code constantly: hex for colors and byte values, binary for bit manipulation, decimal for everything else. But there's a long tail of less-common bases that solve specific problems.
- Octal (base 8) — three bits per digit. The historical reason Unix file permissions are written as
755or644: each digit is exactly three permission bits (read/write/execute). Otherwise rarely used. - Base 32 (RFC 4648) — uses A-Z and 2-7. Designed to be safely readable when written out or transmitted by voice (no confusing 0/O or 1/l/I). Used in TOTP secret keys for two-factor authentication.
- Base 36 — uses 0-9 and a-z. Common for short URL identifiers when you want case-insensitive matching.
parseInt('xyz', 36)works natively in JavaScript. - Base 58 — Bitcoin's invention. Standard alphanumeric (0-9 a-z A-Z) minus 0, O, I, and l — the four characters most often confused with each other. Used in Bitcoin addresses, IPFS hashes, and modern short-URL services that want to balance length with readability.
- Base 62 — full alphanumeric (0-9 a-z A-Z). Maximum density for URL-safe identifiers. YouTube video IDs are base 64 (with - and _); but most short-URL services use base 62 to avoid special characters entirely.
The largest number JavaScript can convert safely
JavaScript's parseInt(s, base) and n.toString(base) work on regular 64-bit floats. The safe integer range is ±253. Beyond that, you start losing precision — convert 2^60 from decimal to binary and back, and you'll get a different number.
For arbitrary-precision conversion, use BigInt: BigInt('123456789012345678901234567890').toString(16). This tool uses BigInt internally so very large numbers convert correctly. Limits: base 2-36 natively; bases 37-62 use a custom alphabet.
Common conversion patterns
// Decimal to hex (lowercase, 2-digit padded for bytes)
(255).toString(16).padStart(2, '0') // "ff"
// Hex to decimal
parseInt('ff', 16) // 255
// Decimal to binary, padded
(13).toString(2).padStart(8, '0') // "00001101"
// Binary to decimal
parseInt('00001101', 2) // 13
// BigInt for arbitrary size
BigInt('0xffffffffffffffff').toString()
// "18446744073709551615"
// Base 36 short identifier from timestamp
Date.now().toString(36) // "lvqe1g3z"
Edge cases this tool handles
- Leading zeros are preserved on input but not on output (they're not significant). Binary "00001101" and "1101" convert to the same decimal 13.
- Hex inputs accept the "0x" prefix commonly used in code. "0xFF" and "FF" both work as hex.
- Letters are case-insensitive for bases up to 36. "AB" and "ab" in base 16 are both 171.
- Bases 37-62 use a custom alphabet (0-9, a-z, A-Z) and are case-sensitive — uppercase and lowercase have different values.
- Negative numbers are supported via a leading minus sign. The conversion converts the absolute value and prepends the sign.
- Decimal fractions are NOT supported — this tool converts integers only. For fraction-to-binary, the algorithm is iterative and outside scope.
Common use cases
- Convert between binary/decimal/hex while debugging
- Decode Bitcoin or IPFS base-58 identifiers
- Convert large integers (BigInt range) without precision loss
- Work with file permission octal codes
Frequently asked questions
What's the difference between base 58 and base 62?
Base 62 uses the full alphanumeric set (0-9, a-z, A-Z). Base 58 (Bitcoin's invention) removes 0, O, I, and l — the four characters most often confused with each other. Base 62 is denser per character; base 58 is more readable when written by hand.
Why use BigInt instead of regular numbers?
JavaScript regular numbers (and most languages' default integers) lose precision above 2⁵³. Converting a 20-digit decimal to binary and back via floats gives a different answer. BigInt has no precision limit — you can convert numbers thousands of digits long correctly.
What's base 36 used for?
It uses 0-9 and a-z (case-insensitive). Common for short URL identifiers and timestamps. <code>Date.now().toString(36)</code> in JavaScript gives a compact alphanumeric timestamp.
Why are octal file permissions like 755 and 644?
Each octal digit (0-7) is exactly 3 bits, matching the read/write/execute permission triplet. 755 = rwx r-x r-x = owner has full, group and others have read+execute.