$ snippet format-bytes-numbers

Format bytes and numbers for humans

'1.2 MB', '3,456,789' and '$1,234.50' using Intl.NumberFormat — correct for every locale.

JavaScript
/** 1536 → "1.5 KB" (decimal, like macOS/disks) or "1.5 KiB" with binary: true. */
function formatBytes(bytes, { decimals = 1, binary = false } = {}) {
  if (!Number.isFinite(bytes) || bytes < 0) return "—";
  const base = binary ? 1024 : 1000;
  const units = binary ? ["B", "KiB", "MiB", "GiB", "TiB", "PiB"] : ["B", "KB", "MB", "GB", "TB", "PB"];
  const i = bytes === 0 ? 0 : Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(base)));
  const value = bytes / base ** i;
  return `${value.toFixed(i === 0 ? 0 : decimals)} ${units[i]}`;
}

/** Thousands separators, localized: 1234567.891 → "1,234,567.89" (en) / "1.234.567,89" (de). */
function formatNumber(n, locale = undefined, options = {}) {
  return new Intl.NumberFormat(locale, { maximumFractionDigits: 2, ...options }).format(n);
}

/** Currency: formatCurrency(1234.5, "USD") → "$1,234.50" */
function formatCurrency(n, currency, locale = undefined) {
  return new Intl.NumberFormat(locale, { style: "currency", currency }).format(n);
}

/** Compact: 12800 → "12.8K", 3400000 → "3.4M" */
function formatCompact(n, locale = undefined) {
  return new Intl.NumberFormat(locale, { notation: "compact", maximumFractionDigits: 1 }).format(n);
}

How it works

Never build number strings with regex hacks like replace(/\B(?=(\d{3})+(?!\d))/g, ",") — it breaks for locales that use spaces or periods as separators, and for negative decimals. Intl.NumberFormat is built in, fast when you reuse the instance, and handles currency symbols, compact notation and rounding rules.

Gotchas

Try it
Result
Ad slot