Base64 v JavaScriptu: btoa(), Buffer a Unicode

·Front-end & Node.js Developer·ZkontrolovánoSophie Laurent·Publikováno

Používejte bezplatný Base64 Encode Online přímo v prohlížeči — bez instalace.

Vyzkoušet Base64 Encode Online online →

Když vkládáte obrázek do CSS data URI, předáváte přihlašovací údaje v HTTP hlavičce Authorization nebo ukládáte binární certifikát do proměnné prostředí, potřebujete spolehlivě kódovat data v Base64 v JavaScriptu — jak v prohlížeči, tak v Node.js. JavaScript poskytuje dvě různá vestavěná API:btoa() pro prostředí prohlížeče (dostupné také v Node.js 16+) a Buffer.from() pro Node.js — každé s různými omezeními ohledně Unicode, binárních dat a URL bezpečnosti. Pro rychlé jednorázové kódování bez psaní kódu Base64 Encoder od ToolDeck to zvládne okamžitě v prohlížeči. Tento průvodce pokrývá obě prostředí s příklady připravenými pro produkci: zpracování Unicode, URL-bezpečné varianty, kódování souborů a odpovědí API, použití CLI a čtyři chyby, které neustále způsobují bugy ve skutečných projektech.

  • btoa() je nativní pro prohlížeče a od Node.js 16+ dostupná globálně, ale přijímá pouze Latin-1 (kódové body 0–255) — vstup v Unicode způsobí DOMException
  • Buffer.from(text, "utf8").toString("base64") je ekvivalent pro Node.js, který nativně zpracovává Unicode bez dalších kroků
  • URL-bezpečný Base64 nahrazuje + → -, / → _ a odstraňuje padding = — použijte Buffer.from().toString("base64url") v Node.js 18+ pro jednořádkové řešení
  • Pro binární data (ArrayBuffer, Uint8Array, soubory) použijte Buffer v Node.js nebo přístup arrayBuffer() + Uint8Array v prohlížeči — nikdy response.text()
  • Uint8Array.prototype.toBase64() (TC39 Stage 3) je již dostupný v Node.js 22+ a Chrome 130+ a sjednotí obě prostředí

Co je kódování Base64?

Base64 převádí libovolná binární data na řetězec sestavený z 64 tisknutelných ASCII znaků: A–Z, a–z, 0–9, + a /. Každé 3 bajty vstupních dat se mapují přesně na 4 znaky Base64; pokud délka vstupu není násobkem 3, připojí se jeden nebo dva znaky = jako padding. Zakódovaný výstup je vždy přibližně o 33 % větší než originál.

Base64 není šifrování — neposkytuje žádnou důvěrnost. Kdokoli se zakódovaným řetězcem ho může dekódovat jedním voláním funkce. Účelem Base64 je bezpečný přenos: mnoho protokolů a formátů úložišť bylo navrženo pro 7-bitový ASCII text a nedokáže zpracovat libovolné binární bajty. Base64 tento rozdíl překlenuje. Běžné případy použití v JavaScriptu zahrnují data URI pro vkládání prostředků, hlavičky HTTP Basic Auth, segmenty JWT tokenů, e-mailové přílohy MIME a ukládání binárních blobů v JSON API.

Before · text
After · text
deploy-bot:sk-prod-a7f2c91e4b3d8
ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

btoa() — nativní funkce prohlížeče pro kódování

btoa() (binary-to-ASCII) je dostupná v prohlížečích od IE10 a stala se globální v Node.js 16.0 v rámci iniciativy WinterCG. Funguje také nativně v Deno, Bun a Cloudflare Workers. Není potřeba žádný import.

Funkce přijímá jeden řetězcový argument a vrací jeho zakódovanou podobu v Base64. Symetrická protější funkce atob() (ASCII-to-binary) ho dekóduje zpět. Obě jsou synchronní a pracují s konstantní pamětí vzhledem k velikosti vstupu.

Minimální funkční příklad

JavaScript (browser / Node.js 16+)
// Kódování páru přihlašovacích údajů API pro hlavičku HTTP Basic Auth
const serviceId  = 'deploy-bot'
const apiKey     = 'sk-prod-a7f2c91e4b3d8'

const credential = btoa(`${serviceId}:${apiKey}`)
// → 'ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg='

const headers = new Headers({
  Authorization: `Basic ${credential}`,
  'Content-Type': 'application/json',
})

console.log(headers.get('Authorization'))
// Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

Dekódování pomocí atob()

JavaScript
// Cesta tam a zpět: kódování, přenos, dekódování
const payload = 'service:payments region:eu-west-1 env:production'

const encoded = btoa(payload)
const decoded = atob(encoded)

console.log(encoded)
// c2VydmljZTpwYXltZW50cyByZWdpb246ZXUtd2VzdC0xIGVudjpwcm9kdWN0aW9u

console.log(decoded === payload) // true
Poznámka:btoa() a atob() jsou součástí WinterCG Minimum Common API — stejné specifikace, která řídí Fetch, URL a crypto v prostředích mimo prohlížeč. Chovají se identicky v Node.js 16+, Bun, Deno a Cloudflare Workers.

Zpracování Unicode a znaků mimo ASCII

Nejčastější past btoa() je její přísné omezení na Latin-1. Jakýkoli znak s kódovým bodem vyšším než U+00FF způsobí okamžitou výjimku:

JavaScript
btoa('Müller & Søren') // ❌ Uncaught DOMException: String contains an invalid character
btoa('résumé')         // ❌ 'é' is U+00E9 = 233 — within Latin-1, this one actually works
btoa('田中太郎')         // ❌ Throws — all CJK characters are above U+00FF

Správný přístup je nejprve zakódovat řetězec do bajtů UTF-8 a pak tyto bajty zakódovat do Base64. JavaScript poskytuje TextEncoder přesně pro tento účel:

Přístup s TextEncoder — bezpečný pro jakýkoli Unicode vstup

JavaScript (browser + Node.js 16+)
// Pomocné funkce pro Unicode-bezpečný Base64
function toBase64(text: string): string {
  const bytes = new TextEncoder().encode(text)
  const chars = Array.from(bytes, byte => String.fromCharCode(byte))
  return btoa(chars.join(''))
}

function fromBase64(encoded: string): string {
  const binary = atob(encoded)
  const bytes  = Uint8Array.from(binary, ch => ch.charCodeAt(0))
  return new TextDecoder().decode(bytes)
}

// Funguje s jakýmkoli jazykem nebo písmem
const orderNote = 'Potvrzeno: Jakub Novák — sklad v Brně, množství: 250'
const encoded   = toBase64(orderNote)
const decoded   = fromBase64(encoded)

console.log(encoded)
// UG90dnJ6ZW5vOiBKYWt1YiBOb3bDoWsgLS0gc2tsYWQgdiBCcm7EmywgbW5venN0dsOtOiAyNTA=

console.log(decoded === orderNote) // true
Poznámka:Pokud jste již v Node.js, přeskočte obejití s TextEncoder úplně — použijte Buffer.from(text, 'utf8').toString('base64'). Zpracovává Unicode nativně a je rychlejší pro velké řetězce.

Buffer.from() v Node.js — kompletní průvodce s příklady

V Node.js je Buffer idiomatické API pro všechny operace s binárními daty, včetně konverze kódování. Předchází TextEncoder o roky a zůstává preferovanou volbou pro serverový kód. Klíčové výhody oproti btoa(): nativní podpora UTF-8, zpracování binárních dat a zkratka kódování 'base64url' dostupná od Node.js 18.

Základní kódování a dekódování textu

Node.js
// Kódování konfiguračního objektu serveru pro uložení do proměnné prostředí
const dbConfig = JSON.stringify({
  host:           'db-primary.internal',
  port:           5432,
  database:       'analytics_prod',
  maxConnections: 100,
  ssl:            { rejectUnauthorized: true },
})

const encoded = Buffer.from(dbConfig, 'utf8').toString('base64')
console.log(encoded)
// eyJob3N0IjoiZGItcHJpbWFyeS5pbnRlcm5hbCIsInBvcnQiOjU0MzIsImRhdGFiYXNlIjoiYW5h...

// Dekódování zpět
const decoded = Buffer.from(encoded, 'base64').toString('utf8')
const config  = JSON.parse(decoded)

console.log(config.host)           // db-primary.internal
console.log(config.maxConnections) // 100

Kódování binárních souborů z disku

Node.js
import { readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'

// Čteme TLS certifikát a kódujeme ho pro vložení do konfiguračního souboru
const certPem     = readFileSync(join(process.cwd(), 'ssl', 'server.crt'))
const certBase64  = certPem.toString('base64')

// Uložení jako jednořádkový řetězec — vhodné pro proměnné prostředí nebo JSON konfigurace
writeFileSync('./dist/cert.b64', certBase64, 'utf8')

console.log(`Certifikát zakódován: ${certBase64.length} znaků`)
// Certifikát zakódován: 2856 znaků

// Obnovení binárního certifikátu ze zakódované hodnoty
const restored = Buffer.from(certBase64, 'base64')
console.log(restored.equals(certPem)) // true

Asynchronní kódování souborů s ošetřením chyb

Node.js
import { readFile } from 'node:fs/promises'

async function encodeFileToBase64(filePath: string): Promise<string> {
  try {
    const buffer = await readFile(filePath)
    return buffer.toString('base64')
  } catch (err) {
    const code = (err as NodeJS.ErrnoException).code
    if (code === 'ENOENT') throw new Error(`Soubor nenalezen: ${filePath}`)
    if (code === 'EACCES') throw new Error(`Přístup odepřen: ${filePath}`)
    throw err
  }
}

// Kódování PDF pro přílohu e-mailu
const reportBase64 = await encodeFileToBase64('./reports/q1-financials.pdf')

const emailPayload = {
  to:          'finance-team@company.internal',
  subject:     'Finanční zpráva za Q1',
  attachments: [{
    filename:    'q1-financials.pdf',
    content:     reportBase64,
    encoding:    'base64',
    contentType: 'application/pdf',
  }],
}

console.log(`Příloha: ${reportBase64.length} znaků`)

Funkce Base64 v JavaScriptu — přehled parametrů

Na rozdíl od modulu base64 v Pythonu nemá JavaScript jedinou sjednocenou funkci Base64. API závisí na cílovém prostředí. Zde je kompletní přehled všech nativních přístupů:

FunkceTyp vstupuUnicodeURL-bezpečnostDostupné v
btoa(string)string (Latin-1)❌ throws above U+00FF❌ manual replaceBrowser, Node 16+, Bun, Deno
atob(string)Base64 string❌ returns binary string❌ manual replaceBrowser, Node 16+, Bun, Deno
Buffer.from(src, enc) .toString(enc)string | Buffer | Uint8Array✅ utf8 encoding✅ base64url in Node 18+Node.js, Bun
TextEncoder().encode(str) + btoa()string (any Unicode)✅ via UTF-8 bytes❌ manual replaceBrowser, Node 16+, Deno
Uint8Array.toBase64() (TC39)Uint8Array✅ binary✅ omitPadding + alphabetChrome 130+, Node 22+

Signatura Buffer.from(src, enc).toString(enc) přijímá několik hodnot kódování relevantních pro Base64:

"base64"
Standardní Base64 (RFC 4648 §4). Používá + a / s paddingem =.
"base64url"
URL-bezpečný Base64 (RFC 4648 §5, Node.js 18+). Používá - a _ bez paddingu.
"utf8"
Výchozí pro řetězcové zdroje. Použijte, když zdrojem je čitelný text.
"binary"
Latin-1 / ISO-8859-1. Použijte, když zdrojem je surový binární řetězec (např. z atob()).

URL-bezpečný Base64 — kódování pro JWT, URL a názvy souborů

Standardní Base64 používá + a /, které jsou v URL rezervovány — + se v query stringech dekóduje jako mezera a / je oddělovač cesty. JWT, parametry URL, názvy souborů a hodnoty cookie vyžadují URL-bezpečnou variantu: +-, /_, koncové = se odstraní.

Prohlížeč — ruční náhrada znaků

JavaScript (browser)
function toBase64Url(text: string): string {
  // For ASCII-safe input (e.g., JSON with only ASCII chars)
  return btoa(text)
    .replace(/+/g, '-')
    .replace(///g, '_')
    .replace(/=/g, '')
}

function fromBase64Url(encoded: string): string {
  // Restore standard Base64 characters and padding before decoding
  const base64  = encoded.replace(/-/g, '+').replace(/_/g, '/')
  const padded  = base64 + '==='.slice(0, (4 - base64.length % 4) % 4)
  return atob(padded)
}

// JWT header — must be URL-safe Base64
const header  = JSON.stringify({ alg: 'HS256', typ: 'JWT' })
const encoded = toBase64Url(header)
console.log(encoded) // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

const decoded = fromBase64Url(encoded)
console.log(decoded) // {"alg":"HS256","typ":"JWT"}

Node.js 18+ — nativní kódování 'base64url'

Node.js 18+
// Node.js 18 added 'base64url' as a first-class Buffer encoding
const sessionPayload = JSON.stringify({
  userId:     'usr_9f2a1c3e8b4d',
  role:       'editor',
  workspaceId:'ws_3a7f91c2',
  exp:        Math.floor(Date.now() / 1000) + 3600,
})

const encoded = Buffer.from(sessionPayload, 'utf8').toString('base64url')
// No + or / or = characters in the output
// eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9

const decoded = Buffer.from(encoded, 'base64url').toString('utf8')
console.log(JSON.parse(decoded).role) // editor

Kódování souborů a odpovědí API v JavaScriptu

V produkčním kódu se kódování Base64 nejčastěji aplikuje na přenášené soubory a odpovědi z externích API, které doručují binární obsah. Přístupy se liší mezi prohlížečem a Node.js a binární data vyžadují zvláštní pozornost.

Prohlížeč — kódování souboru z elementu input

JavaScript (browser)
// Modern approach: File.arrayBuffer() (Chrome 76+, Firefox 69+, Safari 14+)
async function encodeFile(file: File): Promise<string> {
  const buffer = await file.arrayBuffer()
  const bytes  = new Uint8Array(buffer)
  const chars  = Array.from(bytes, b => String.fromCharCode(b))
  return btoa(chars.join(''))
}

const uploadInput = document.getElementById('avatar') as HTMLInputElement

uploadInput.addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return

  try {
    const encoded = await encodeFile(file)
    const dataUri = `data:${file.type};base64,${encoded}`

    // Náhled obrázku
    const img   = document.getElementById('preview') as HTMLImageElement
    img.src     = dataUri
    img.hidden  = false

    console.log(`Zakódováno ${file.name} (${file.size} bajtů) → ${encoded.length} znaků Base64`)
  } catch (err) {
    console.error('Kódování selhalo:', err)
  }
})

Načítání Base64-zakódovaných binárních dat z API

JavaScript
// GitHub Contents API returns file content as Base64 with embedded newlines
async function fetchRepoFile(
  owner: string,
  repo:  string,
  path:  string,
  token: string,
): Promise<string> {
  const res = await fetch(
    `https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
    {
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: 'application/vnd.github.v3+json',
      },
    }
  )

  if (!res.ok) throw new Error(`GitHub API ${res.status}: ${res.statusText}`)

  const data = await res.json() as { content: string; encoding: string; size: number }

  if (data.encoding !== 'base64') {
    throw new Error(`Unexpected encoding from GitHub: ${data.encoding}`)
  }

  // GitHub wraps output at 60 chars — strip newlines before decoding
  const clean = data.content.replace(/\n/g, '')
  return atob(clean)
}

const openApiSpec = await fetchRepoFile(
  'acme-corp', 'platform-api', 'openapi.json', process.env.GITHUB_TOKEN!
)
const spec = JSON.parse(openApiSpec)
console.log(`API version: ${spec.info.version}`)

Když potřebujete jen zkontrolovat zakódovanou odpověď při ladění API bez psaní skriptu, vložte hodnotu Base64 přímo do Base64 Encoder — dekóduje také, s okamžitým výstupem. Užitečné pro kontrolu odpovědí GitHub API, JWT payloadů a podpisů webhook.

Kódování Base64 z příkazové řádky v Node.js a shellu

Pro skripty CI/CD, cíle Makefile nebo jednorázové ladění zřídka potřebujete celý skript. Systémové nástroje i jednořádkové příkazy Node.js pokrývají většinu případů multiplatformně.

bash
# ── macOS / Linux system base64 ───────────────────────────────────────
# Standard encoding
echo -n "deploy-bot:sk-prod-a7f2c91e4b3d8" | base64
# ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

# URL-safe variant (replace chars and strip padding)
echo -n "deploy-bot:sk-prod-a7f2c91e4b3d8" | base64 | tr '+/' '-_' | tr -d '='

# Encode a file inline (macOS: -b 0 removes line wrapping; Linux: --wrap=0)
base64 -b 0 ./config/production.json
# or on Linux:
base64 --wrap=0 ./config/production.json

# Decode
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 --decode

# ── Node.js one-liner — works on Windows too ───────────────────────────
node -e "process.stdout.write(Buffer.from(process.argv[1]).toString('base64'))" "my:secret"
# bXk6c2VjcmV0

# URL-safe from Node.js 18+
node -e "process.stdout.write(Buffer.from(process.argv[1]).toString('base64url'))" "my:secret"
# bXk6c2VjcmV0  (same here since there are no special chars)

# Decode in Node.js
node -e "console.log(Buffer.from(process.argv[1], 'base64').toString())" "ZGVwbG95LWJvdA=="
Poznámka:Na macOS base64 ve výchozím nastavení zalamuje výstup po 76 znacích. To narušuje následné parsování. Vždy přidávejte -b 0 (macOS) nebo --wrap=0 (Linux), když potřebujete jednořádkový výsledek — například při zápisu do proměnné prostředí nebo konfiguračního pole.

Vysoce výkonná alternativa: js-base64

Vestavěná API jsou vhodná pro většinu případů použití. Hlavním důvodem pro použití knihovny je konzistence napříč prostředími: pokud dodáváte balíček, který běží v prohlížeči i Node.js, použití Buffer vyžaduje buď detekci prostředí nebo konfiguraci bundleru, zatímco btoa() vyžaduje obejití pro Unicode. js-base64 (100M+ stažení týdně na npm) toto řeší transparentně.

bash
npm install js-base64
# or
pnpm add js-base64
JavaScript
import { toBase64, fromBase64, toBase64Url, fromBase64Url, isValid } from 'js-base64'

// Standard encoding — Unicode-safe, works in browser and Node.js
const telemetryEvent = JSON.stringify({
  eventId:   'evt_7c3a9f1b2d',
  type:      'checkout_completed',
  currency:  'EUR',
  amount:    14900,
  userId:    'usr_4e2b8d6a5c',
  timestamp: 1717200000,
})

const encoded    = toBase64(telemetryEvent)
const urlEncoded = toBase64Url(telemetryEvent) // No +, /, or = characters

const decoded = fromBase64(encoded)
console.log(JSON.parse(decoded).type) // checkout_completed

// Binary data — pass a Uint8Array as second argument
const pngMagicBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
const binaryEncoded = toBase64(pngMagicBytes, true) // true = binary mode

// Validation before decoding
const suspicious = 'not!valid@base64#'
console.log(isValid(suspicious)) // false

Pod kapotou js-base64 používá nativní Buffer, když je dostupný, a v prohlížeči se vrací k implementaci v čistém JS. Je 2–3× rychlejší než přístup TextEncoder+btoa pro velké Unicode řetězce a symetrické API (toBase64 / fromBase64) eliminuje nutnost pamatovat si, ve kterém směru pracují btoa a atob.

Kódování velkých binárních souborů pomocí streamů Node.js

Když potřebujete kódovat soubory větší než ~50 MB, načtení celého souboru do paměti pomocí readFileSync() se stává problémem. Streamy Node.js umožňují zpracovávat data po částech — Base64 kódování má ale omezení: musíte předávat kodéru násobky 3 bajtů, abyste se vyhnuli nesprávnému paddingu na hranicích chunků.

Node.js
import { createReadStream, createWriteStream } from 'node:fs'
import { pipeline } from 'node:stream/promises'

// Stream a large binary file to a Base64-encoded output file
async function streamEncodeToBase64(
  inputPath:  string,
  outputPath: string,
): Promise<void> {
  const readStream  = createReadStream(inputPath, { highWaterMark: 3 * 1024 * 256 }) // 768 KB chunks (multiple of 3)
  const writeStream = createWriteStream(outputPath, { encoding: 'utf8' })

  let buffer = Buffer.alloc(0)

  await pipeline(
    readStream,
    async function* (source) {
      for await (const chunk of source) {
        buffer = Buffer.concat([buffer, chunk as Buffer])

        // Encode in complete 3-byte groups to avoid mid-stream padding
        const remainder = buffer.length % 3
        const safe      = buffer.subarray(0, buffer.length - remainder)
        buffer          = buffer.subarray(buffer.length - remainder)

        if (safe.length > 0) yield safe.toString('base64')
      }
      // Flush remaining bytes (may add 1 or 2 '=' padding chars)
      if (buffer.length > 0) yield buffer.toString('base64')
    },
    writeStream,
  )
}

// Usage: encode a 200 MB video attachment
await streamEncodeToBase64(
  './uploads/product-demo.mp4',
  './dist/product-demo.b64',
)
console.log('Streamové kódování dokončeno')
Poznámka:Velikost chunku musí být násobkem 3 bajtů, aby se zabránilo falešnému = paddingu uprostřed výstupu. Příklad používá 3 * 1024 * 256 = 786 432 bajtů (768 KB) — upravte highWaterMark podle svého paměťového rozpočtu. Pro soubory do 50 MB je readFile() + Buffer.toString('base64') jednodušší a dostatečně rychlé.

Časté chyby

Prošel jsem mnoho JavaScript projektů s kódováním Base64 a tyto čtyři chyby se vyskytují konzistentně — často neodhaleny, dokud non-ASCII znak nebo binární soubor nedosáhne kódovací cesty v produkci.

Chyba 1 — Předání Unicode přímo do btoa()

Problém: btoa() přijímá pouze znaky s kódovými body 0–255. Znaky jako ñ, emoji nebo CJK ideogramy způsobí okamžitou DOMException. Řešení: nejprve kódujte pomocí TextEncoder, nebo použijte Buffer.from(text, 'utf8').toString('base64') v Node.js.

Before · JavaScript
After · JavaScript
// ❌ DOMException: The string to be encoded contains
//    characters outside of the Latin1 range
const username = 'Jakub Novák'
const encoded  = btoa(username)  // throws
// ✅ Encode as UTF-8 bytes first
function safeEncode(text: string): string {
  const bytes = new TextEncoder().encode(text)
  const chars = Array.from(bytes, b => String.fromCharCode(b))
  return btoa(chars.join(''))
}
const encoded = safeEncode('Jakub Novák')
// SmFrdWIgTm92w6Fr

Chyba 2 — Zapomenutí obnovit padding před atob()

Problém: URL-bezpečný Base64 odstraňuje padding =. Předání řetězce bez paddingu přímo do atob() produkuje nesprávný výstup nebo vyvolá výjimku v závislosti na délce řetězce. Řešení: obnovte + a / a znovu přidejte správné množství paddingu před voláním atob().

Before · JavaScript
After · JavaScript
// ❌ atob() may return wrong data or throw
//    on URL-safe Base64 without padding
const jwtSegment = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ'
const decoded    = atob(jwtSegment) // Unreliable
// ✅ Restore characters and padding first
function decodeBase64Url(input: string): string {
  const b64 = input.replace(/-/g, '+').replace(/_/g, '/')
  const pad = b64 + '==='.slice(0, (4 - b64.length % 4) % 4)
  return atob(pad)
}
const decoded = decodeBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ')
// {"userId":"usr_9f2a1c3e"}

Chyba 3 — Concatenování zakódovaných chunků místo surových bufferů

Problém: Každé volání btoa() nebo .toString('base64') přidává vlastní padding. Concatenování dvou paddingovaných Base64 řetězců produkuje neplatný výstup, protože padding patří pouze na samý konec. Řešení: concatenujte surová data před kódováním.

Before · JavaScript
After · JavaScript
// ❌ Both parts are padded independently —
//    the combined string is not valid Base64
const part1 = Buffer.from('webhook-secret').toString('base64')
// d2ViaG9vay1zZWNyZXQ=  ← has padding
const part2 = Buffer.from('-v2').toString('base64')
// LXYy            ← correct in isolation
const combined = part1 + part2 // ❌ Invalid — padding in the middle
// ✅ Concatenate raw Buffers before encoding
const combined = Buffer.concat([
  Buffer.from('webhook-secret'),
  Buffer.from('-v2'),
]).toString('base64')
// d2ViaG9vay1zZWNyZXQtdjI= — single valid Base64 string

Chyba 4 — Použití response.text() ke čtení binárních dat API před kódováním

Problém: response.text() interpretuje surové bajty jako UTF-8 a nahrazuje nerozpoznané bajtové sekvence náhradním znakem U+FFFD. Jakýkoli binární obsah — obrázky, PDF, audio — je tiše poškozen dříve, než dosáhne btoa(). Řešení: použijte response.arrayBuffer() pro získání surových bajtů.

Before · JavaScript
After · JavaScript
// ❌ response.text() corrupts binary data
const res     = await fetch('/api/exports/invoice.pdf')
const text    = await res.text()   // ❌ PDF bytes mangled as UTF-8
const encoded = btoa(text)         // ❌ Corrupted Base64
// ✅ arrayBuffer() preserves raw bytes
const res     = await fetch('/api/exports/invoice.pdf')
const buffer  = await res.arrayBuffer()
const bytes   = new Uint8Array(buffer)
const chars   = Array.from(bytes, b => String.fromCharCode(b))
const encoded = btoa(chars.join('')) // ✅ Valid Base64

Metody Base64 v JavaScriptu — rychlé srovnání

MetodaUnicodeBinární dataURL-bezpečnostProstředíVyžaduje instalaci
btoa() / atob()❌ Latin-1❌ workaround needed❌ manual replaceBrowser, Node 16+, Bun, DenoNe
TextEncoder + btoa()✅ UTF-8✅ via Uint8Array❌ manual replaceBrowser, Node 16+, DenoNe
Buffer.from().toString()✅ utf8✅ native✅ base64url (Node 18+)Node.js, BunNe
Uint8Array.toBase64() (TC39)✅ binary✅ native✅ alphabet optionChrome 130+, Node 22+Ne
js-base64✅ always✅ Uint8Array✅ built-inUniversalnpm install

Používejte btoa() pouze tehdy, když vstup je prokazatelně jen ASCII — hexadecimální hashe, numerická ID nebo předem ověřené řetězce Latin-1. Pro uživatelský text v prohlížeči použijte TextEncoder + btoa(). Pro veškerý serverový kód v Node.js je Buffer správnou výchozí volbou. Pro knihovny, které musí běžet v obou prostředích bez konfigurace bundleru, js-base64 odstraňuje všechny okrajové případy.

Často kladené otázky

Proč btoa() vyvolává "InvalidCharacterError" pro můj řetězec?
btoa() přijímá pouze znaky s kódovými body v rozsahu 0–255 (Latin-1 / ISO-8859-1). Jakýkoli znak nad U+00FF — včetně většiny cyrilice, arabštiny, CJK ideogramů a mnoha emoji — způsobí DOMException. Řešení závisí na vašem prostředí: v prohlížeči nejprve zakódujte do bajtů UTF-8 pomocí TextEncoder, převeďte každý bajt na znak pomocí String.fromCharCode() a pak zavolejte btoa(). V Node.js použijte Buffer.from(text, 'utf8').toString('base64'), který zpracovává Unicode nativně.
Je btoa() dostupná v Node.js bez jakéhokoli importu?
Ano, od Node.js 16.0. Obě funkce — btoa() a atob() — jsou registrovány jako globální — není potřeba žádný import. Chovají se identicky jako jejich protějšky v prohlížeči, včetně omezení Latin-1. Pro serverový kód Node.js je Buffer.from() stále preferován před btoa(), protože zpracovává UTF-8 nativně, podporuje binární data bez obejití a má možnost 'base64url' přidanou v Node.js 18.
Jaký je rozdíl mezi standardním Base64 a URL-bezpečným Base64?
Standardní Base64 (RFC 4648 §4) používá + pro hodnotu 62, / pro hodnotu 63 a = pro padding. Tyto znaky mají speciální význam v URL: + je interpretován jako mezera v query stringech a / je oddělovač cesty. URL-bezpečný Base64 (RFC 4648 §5) nahrazuje - za + a _ za / a obvykle zcela vynechává padding =. JWT používají URL-bezpečný Base64 pro všechny tři segmenty. V Node.js 18+ Buffer.from(text).toString('base64url') produkuje URL-bezpečný formát přímo.
Jak zakóduji obrázek do Base64 pro CSS data URI v JavaScriptu?
V prohlížeči: použijte file.arrayBuffer() ke čtení binárních dat, převeďte na Uint8Array a pak zavolejte btoa(Array.from(bytes, b => String.fromCharCode(b)).join('')). Sestavte data URI jako 'data:' + file.type + ';base64,' + encoded. V Node.js: const encoded = fs.readFileSync('./image.png').toString('base64') a připojte MIME typ. Pro SVG soubory můžete často Base64 zcela přeskočit a použít URL-enkódované data URI — to je čitelnější a mírně menší.
Mohu kódovat a dekódovat Base64 bez npm knihovny v prohlížeči?
Ano. Pro vstup pouze s ASCII fungují btoa() a atob() přímo. Pro Unicode dvojice TextEncoder / TextDecoder poskytuje kompletní sadu nástrojů — obě jsou vestavěné ve všech moderních prohlížečích a Node.js 16+. Jediný případ, kdy knihovna skutečně přidává hodnotu, je konzistence napříč prostředími: pokud píšete utilitu, která musí fungovat identicky v prohlížeči i Node.js bez konfigurace bundleru, js-base64 odstraňuje logiku detekce prostředí.
Jak dekóduji obsah Base64 z GitHub API?
GitHub Contents API vrací obsah souboru jako Base64 s vloženými znaky nového řádku (API zalamuje výstup po 60 znacích). Odstraňte je před dekódováním: const clean = data.content.replace(/\n/g, ''); const text = atob(clean);. V Node.js: const text = Buffer.from(data.content.replace(/\n/g, ''), 'base64').toString('utf8');. GitHub vždy používá standardní Base64 (ne URL-bezpečný), takže náhrada + → - nebo / → _ není potřeba.

Související nástroje

Pro rychlé kódování nebo dekódování jediným kliknutím bez psaní kódu vložte řetězec nebo binární data přímo do Base64 Encoder — okamžitě zpracovává standardní i URL-bezpečný režim ve vašem prohlížeči.

Dostupné také v:PythonJava
AC
Alex ChenFront-end & Node.js Developer

Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.

SL
Sophie LaurentTechnický recenzent

Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.