Dekódování Base64 v JavaScriptu — atob() a Buffer

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

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

Vyzkoušet Base64 Decode Online online →

Když ladím produkční problém s autentizací, první věc, po které sáhnu, je Base64 Decoder — JWT payloady, podpisy webhooků a zakódované konfigurační hodnoty se všechny skrývají v Base64 řetězcích. JavaScript nabízí dva primární vestavěné přístupy k dekódování base64: atob() (prohlížeč + Node.js 16+) a Buffer.from(encoded, 'base64').toString() (Node.js) — a chovají se velmi odlišně, když původní data obsahovala znaky Unicode. Pro rychlé jednorázové dekódování bez psaní kódu zvládne Base64 Decoder ToolDecku vše okamžitě v prohlížeči. Tento průvodce pokrývá obě prostředí — zaměřuje se na Node.js 16+ a moderní prohlížeče (Chrome 80+, Firefox 75+, Safari 14+) — s příklady připravenými pro produkci: obnovení UTF-8, URL-safe varianty, dekódování JWT, soubory, odpovědi API, Node.js streamy a čtyři chyby, které důsledně produkují nečitelný výstup v reálných kódových základnách.

  • atob(encoded) je nativní v prohlížeči a dostupná v Node.js 16+ globálně, ale vrací binární řetězec — použijte TextDecoder k obnovení UTF-8 textu z obsahu obsahujícího znaky nad ASCII.
  • Buffer.from(encoded, "base64").toString("utf8") je idiomatický přístup v Node.js a automaticky zpracovává UTF-8 bez dalších kroků.
  • URL-safe Base64 (používaná v JWT) nahrazuje + za -, / za _ a odstraňuje padding =. Před voláním atob() je obnovte, nebo použijte Buffer.from(encoded, "base64url").toString() v Node.js 18+.
  • Před dekódováním odstraňte mezery a konce řádků — GitHub Contents API a mnoho MIME encoderů zalamuje výstup Base64 na 60–76 znacích na řádek.
  • Uint8Array.prototype.fromBase64() (TC39 Stage 3) je již k dispozici v Node.js 22+ a Chrome 130+ a nakonec sjednotí obě prostředí.

Co je dekódování Base64?

Dekódování Base64 je inverzní operace k enkódování — převádí 64znakovou ASCII reprezentaci zpět na původní binární data nebo text. Každé 4 Base64 znaky se mapují přesně na 3 bajty. Znaky = pro zarovnání na konci zakódovaného řetězce říkají dekodéru, kolik extra bajtů bylo přidáno k doplnění poslední 3bajtové skupiny.

Base64 není šifrování — operace je plně reverzibilní kýmkoliv se zakódovaným řetězcem. Jejím účelem je bezpečnost přenosu: protokoly a formáty úložiště navržené pro 7bitový ASCII text nemohou zpracovat libovolné binární bajty, a Base64 tento rozdíl překlenuje. Běžné scénáře dekódování v JavaScriptu zahrnují kontrolu JWT payloadů, rozbalení Base64-kódovaných JSON konfigurací z proměnných prostředí, extrakci binárního obsahu souborů z REST API a dekódování datových URI v prohlížeči.

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

atob() — Nativní dekódovací funkce prohlížeče

atob() (ASCII-to-binary) je dostupná v prohlížečích od IE10 a stala se globální funkcí v Node.js 16.0 jako součást iniciativy kompatibility WinterCG. Funguje také nativně v Deno, Bun a Cloudflare Workers — bez nutnosti importu.

Funkce vrací binární řetězec: JavaScriptový řetězec, kde každý znak má hodnotu kódového bodu rovnou jednomu bajtu (0–255). To je důležité: pokud původní data obsahovala UTF-8 text se znaky nad U+007F (písmena s diakritikou, cyrilice, CJK, emoji), vrácený řetězec je surová bajtová sekvence, nikoli čitelný text. K obnovení použijte TextDecoder (popsáno v další části).

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

JavaScript (browser / Node.js 16+)
// Decoding an HTTP Basic Auth credential pair received in a request header
// Authorization: Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

function parseBasicAuth(header: string): { serviceId: string; apiKey: string } {
  const base64Part = header.replace(/^Basics+/i, '')
  const decoded    = atob(base64Part)
  const [serviceId, apiKey] = decoded.split(':')
  return { serviceId, apiKey }
}

const auth = parseBasicAuth('Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=')

console.log(auth.serviceId) // deploy-bot
console.log(auth.apiKey)    // sk-prod-a7f2c91e4b3d8

Ověření zpětné kompatibility

JavaScript
// Verify lossless recovery for ASCII-only content
const original = 'service:payments region:eu-west-1 env:production'

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

console.log(encoded)
// c2VydmljZTpwYXltZW50cyByZWdpb246ZXUtd2VzdC0xIGVudjpwcm9kdWN0aW9u

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

Obnovení UTF-8 textu po dekódování

Nejčastější úskalí s atob() je nepochopení jejího návratového typu. Když byl původní text zakódován jako UTF-8 před Base64, vrátí atob() Latin-1 binární řetězec, nikoli čitelný text:

JavaScript
// 'Алексей Иванов' was UTF-8 encoded then Base64 encoded before transmission
const encoded = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy'

// ❌ atob() returns the raw UTF-8 bytes as a Latin-1 string — garbled output
console.log(atob(encoded))
// "Алексей Р˜РІР°РЅРѕРІ"  ← byte values misread as Latin-1

Správný přístup používá TextDecoder k interpretaci surových bajtů jako UTF-8:

Přístup s TextDecoder — bezpečný pro libovolný Unicode výstup

JavaScript (browser + Node.js 16+)
// Unicode-safe Base64 decode utilities
function fromBase64(encoded: string): string {
  const binary = atob(encoded)
  const bytes  = Uint8Array.from(binary, ch => ch.charCodeAt(0))
  return new TextDecoder().decode(bytes)
}

function toBase64(text: string): string {
  const bytes = new TextEncoder().encode(text)
  const chars = Array.from(bytes, byte => String.fromCharCode(byte))
  return btoa(chars.join(''))
}

// Works with any language or script
const orderNote = 'Confirmed: 田中太郎 — São Paulo warehouse, qty: 250'
const encoded   = toBase64(orderNote)
const decoded   = fromBase64(encoded)

console.log(decoded === orderNote) // true
console.log(decoded)
// Confirmed: 田中太郎 — São Paulo warehouse, qty: 250
Poznámka:V Node.js přeskočte krok s TextDecoder úplně — použijte Buffer.from(encoded, 'base64').toString('utf8'). Dekódované bajty interpretuje automaticky jako UTF-8 a pro velké vstupy je rychlejší.

Buffer.from() v Node.js — Kompletní průvodce dekódováním

V Node.js je Buffer idiomatické API pro všechny binární operace včetně dekódování Base64. Zpracovává UTF-8 nativně, vrací správný Buffer (binárně bezpečný) a od Node.js 18 podporuje zkratku kódování 'base64url' pro URL-safe varianty.

Dekódování konfigurační proměnné prostředí

Node.js
// Server config stored as Base64 in an env variable (avoids JSON escaping in shell)
// DB_CONFIG=eyJob3N0IjoiZGItcHJpbWFyeS5pbnRlcm5hbCIsInBvcnQiOjU0MzIsImRhdGFiYXNlIjoiYW5hbHl0aWNzX3Byb2QiLCJtYXhDb25uZWN0aW9ucyI6MTAwfQ==

const raw = Buffer.from(process.env.DB_CONFIG!, 'base64').toString('utf8')
const dbConfig = JSON.parse(raw)

console.log(dbConfig.host)           // db-primary.internal
console.log(dbConfig.port)           // 5432
console.log(dbConfig.maxConnections) // 100

Obnovení binárního souboru ze souboru .b64

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

// Read the Base64-encoded certificate and restore the original binary
const encoded = readFileSync(join(process.cwd(), 'dist', 'cert.b64'), 'utf8').trim()
const certBuf  = Buffer.from(encoded, 'base64')

writeFileSync('./ssl/server.crt', certBuf)

console.log(`Restored ${certBuf.length} bytes`)
// Restored 2142 bytes

Asynchronní dekódování s ošetřením chyb

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

async function decodeBase64File(
  encodedPath: string,
  outputPath:  string,
): Promise<number> {
  try {
    const encoded = await readFile(encodedPath, 'utf8')
    const binary  = Buffer.from(encoded.trim(), 'base64')
    await writeFile(outputPath, binary)
    return binary.length
  } catch (err) {
    const code = (err as NodeJS.ErrnoException).code
    if (code === 'ENOENT') throw new Error(`File not found: ${encodedPath}`)
    if (code === 'EACCES') throw new Error(`Permission denied: ${encodedPath}`)
    throw err
  }
}

// Restore a PDF stored as Base64
const bytes = await decodeBase64File('./uploads/invoice.b64', './out/invoice.pdf')
console.log(`Decoded ${bytes} bytes — PDF restored`)

Dekódovací funkce Base64 — Reference parametrů

Rychlá reference parametrů dvou primárních nativních dekódovacích API, formátovaná pro použití jako vyhledávací tabulka při psaní nebo revizi kódu.

atob(encodedData)

ParametrTypPovinnýPopis
encodedDatastringAnoStandardní Base64 řetězec používající znaky +, /, =. URL-safe varianty (-, _) vyhodí InvalidCharacterError. Mezery nejsou povoleny.
Vrací: binární řetězec — hodnota kódového bodu každého znaku odpovídá jednomu surovému bajtu (0–255). Není to Unicode řetězec; k obnovení UTF-8 textu předejte přes TextDecoder.

Buffer.from(input, inputEncoding) / .toString(outputEncoding)

ParametrTypVýchozíPopis
inputstring | Buffer | TypedArray | ArrayBufferrequiredBase64-kódovaný řetězec k dekódování nebo buffer obsahující zakódované bajty.
inputEncodingBufferEncoding"utf8"Nastavte na "base64" pro standardní Base64 (RFC 4648 §4), nebo "base64url" pro URL-safe Base64 (RFC 4648 §5, Node.js 18+).
outputEncodingstring"utf8"Kódování pro výstup .toString(). Použijte "utf8" pro čitelný text, "binary" pro Latin-1 binární řetězec kompatibilní s výstupem atob().
startinteger0Bajtový offset v dekódovaném Bufferu, od kterého začít číst. Předává se do .toString() jako druhý argument.
endintegerbuf.lengthBajtový offset, kde přestat číst (exkluzivní). Předává se do .toString() jako třetí argument.
Vrací: Buffer z .from(). Vrací string z .toString(). Uchovejte jako Buffer (nevolat .toString()), když je dekódovaný obsah binární — obrázky, PDF, audio.

URL-safe Base64 — Dekódování JWT a URL parametrů

JWT používají URL-safe Base64 (RFC 4648 §5) pro všechny tři segmenty. URL-safe Base64 nahrazuje + za - a / za _ a odstraňuje koncový = padding. Přímé předání tohoto řetězce do atob() bez obnovení produkuje nesprávný výstup nebo vyhodí výjimku.

Prohlížeč — obnovení znaků a paddingu před dekódováním

JavaScript (browser)
function decodeBase64Url(input: string): string {
  const base64 = input.replace(/-/g, '+').replace(/_/g, '/')
  const padded = base64 + '==='.slice(0, (4 - base64.length % 4) % 4)
  const binary = atob(padded)
  const bytes  = Uint8Array.from(binary, ch => ch.charCodeAt(0))
  return new TextDecoder().decode(bytes)
}

// Inspect a JWT payload segment (the middle part between the two dots)
const jwtToken  = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9'
const payload   = decodeBase64Url(jwtToken)
const claims    = JSON.parse(payload)

console.log(claims.userId)      // usr_9f2a1c3e8b4d
console.log(claims.role)        // editor
console.log(claims.workspaceId) // ws_3a7f91c2

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

Node.js 18+
// Node.js 18 added 'base64url' as a first-class Buffer encoding — no manual replace needed
function decodeJwtSegment(segment: string): Record<string, unknown> {
  const json = Buffer.from(segment, 'base64url').toString('utf8')
  return JSON.parse(json)
}

const token   = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9.SIGNATURE'
const [headerB64, payloadB64] = token.split('.')

const header  = decodeJwtSegment(headerB64)
const payload = decodeJwtSegment(payloadB64)

console.log(header.alg)          // HS256
console.log(payload.role)        // editor
console.log(payload.workspaceId) // ws_3a7f91c2

Dekódování Base64 ze souborů a odpovědí API

V produkčním kódu k dekódování Base64 nejčastěji dochází při konzumaci externích API, která doručují obsah v zakódované formě. Oba scénáře mají důležitá úskalí ohledně mezer a binárního vs textového výstupu. Pokud potřebujete jen zkontrolovat zakódovanou odpověď při ladění, vložte ji přímo do Base64 Decoderu — okamžitě zpracovává standardní i URL-safe režimy.

Dekódování obsahu z GitHub Contents API

JavaScript
// GitHub Contents API returns file content as Base64, wrapped at 60 chars per line
async function fetchDecodedFile(
  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 }
  if (data.encoding !== 'base64') throw new Error(`Unexpected encoding: ${data.encoding}`)

  // ⚠️ GitHub wraps at 60 chars — strip newlines before decoding
  const clean = data.content.replace(/\n/g, '')
  return Buffer.from(clean, 'base64').toString('utf8')
}

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

Dekódování Base64-kódovaného binárního souboru z API (prohlížeč)

JavaScript (browser)
// Some APIs return binary content (images, PDFs) as Base64 JSON fields
async function downloadDecodedFile(endpoint: string, authToken: string): Promise<void> {
  const res = await fetch(endpoint, { headers: { Authorization: `Bearer ${authToken}` } })
  if (!res.ok) throw new Error(`Download failed: ${res.status}`)

  const { filename, content, mimeType } = await res.json() as {
    filename: string; content: string; mimeType: string
  }

  // Decode Base64 → binary bytes → Blob
  const binary = atob(content)
  const bytes  = Uint8Array.from(binary, ch => ch.charCodeAt(0))
  const blob   = new Blob([bytes], { type: mimeType })

  // Trigger browser download
  const url = URL.createObjectURL(blob)
  const a   = Object.assign(document.createElement('a'), { href: url, download: filename })
  a.click()
  URL.revokeObjectURL(url)
}

await downloadDecodedFile('/api/reports/latest', sessionStorage.getItem('auth_token')!)

Dekódování Base64 na příkazovém řádku v Node.js a shellu

Pro skripty CI/CD, ladicí sezení nebo jednorázové dekódovací úlohy jsou shellové nástroje a jednolinky Node.js rychlejší než celý skript. Název příznaku se liší mezi macOS a Linuxem.

bash
# ── macOS / Linux system base64 ───────────────────────────────────────
# Standard decoding (macOS uses -D, Linux uses -d)
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 -d   # Linux
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 -D   # macOS

# Decode a .b64 file to its original binary
base64 -d ./dist/cert.b64 > ./ssl/server.crt       # Linux
base64 -D -i ./dist/cert.b64 -o ./ssl/server.crt   # macOS

# URL-safe Base64 — restore + and / before decoding
echo "eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ" | tr '-_' '+/' | base64 -d

# ── Node.js one-liner — works on Windows too ───────────────────────────
node -e "process.stdout.write(Buffer.from(process.argv[1], 'base64').toString())" "ZGVwbG95LWJvdA=="
# deploy-bot

# URL-safe (Node.js 18+)
node -e "process.stdout.write(Buffer.from(process.argv[1], 'base64url').toString())" "eyJhbGciOiJIUzI1NiJ9"
# {"alg":"HS256"}
Poznámka:Na macOS používá příkaz base64 příznak -D k dekódování (velké D), zatímco Linux používá -d (malé d). To tiše naruší CI skripty — použijte jednolinkový skript Node.js, když není zaručeno, že cílová platforma bude Linux.

Výkonná alternativa: js-base64

Hlavní důvod 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 bez konfigurace bundleru, Buffer vyžaduje detekci prostředí a atob() vyžaduje obejití přes TextDecoder.js-base64 (100M+ stažení týdně přes npm) to zvládá transparentně.

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

// Standard decoding — Unicode-safe, works in browser and Node.js
const raw   = fromBase64('eyJldmVudElkIjoiZXZ0XzdjM2E5ZjFiMmQiLCJ0eXBlIjoiY2hlY2tvdXRfY29tcGxldGVkIiwiY3VycmVuY3kiOiJFVVIiLCJhbW91bnQiOjE0OTAwfQ==')
const event = JSON.parse(raw)
console.log(event.type)     // checkout_completed
console.log(event.currency) // EUR

// URL-safe decoding — no manual character replacement needed
const jwtPayload = fromBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciJ9')
const claims     = JSON.parse(jwtPayload)
console.log(claims.role) // editor

// Validate before decoding untrusted input
const untrusted = 'not!valid@base64#'
if (!isValid(untrusted)) {
  console.error('Rejected: invalid Base64 input')
}

// Binary output — second argument true returns Uint8Array
const pngBytes = fromBase64('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==', true)
console.log(pngBytes instanceof Uint8Array) // true

Terminálový výstup se zvýrazněním syntaxe

Při psaní CLI ladicích nástrojů nebo inspekčních skriptů je prostý výstup console.log obtížně čitelný pro velké JSON payloady. chalk (nejstahovanější npm balíček pro barvení terminálu) v kombinaci s dekódováním Base64 produkuje čitelný, přehledný terminálový výstup — užitečný pro inspekci JWT, ladění odpovědí API a audit konfigurací.

bash
npm install chalk
# chalk v5+ is ESM-only — use import, not require
Node.js
import chalk from 'chalk'

// Decode and display any Base64 value with smart type detection
function inspectBase64(encoded: string, label = 'Decoded value'): void {
  let decoded: string
  try {
    decoded = Buffer.from(encoded.trim(), 'base64').toString('utf8')
  } catch {
    console.error(chalk.red('✗ Invalid Base64 input'))
    return
  }

  console.log(chalk.bold.cyan(`\n── ${label} ──`))

  // Attempt JSON pretty-print
  try {
    const parsed = JSON.parse(decoded)
    console.log(chalk.green('Type:'), chalk.yellow('JSON'))
    for (const [key, value] of Object.entries(parsed)) {
      const display = typeof value === 'object' ? JSON.stringify(value) : String(value)
      console.log(chalk.green(`  ${key}:`), chalk.white(display))
    }
    return
  } catch { /* not JSON */ }

  // Plain text fallback
  console.log(chalk.green('Type:'), chalk.yellow('text'))
  console.log(chalk.white(decoded))
}

// Inspect a Base64-encoded JWT payload
const tokenParts = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsImV4cCI6MTcxNzIwMzYwMH0.SIGNATURE'.split('.')
inspectBase64(tokenParts[0], 'JWT Header')
inspectBase64(tokenParts[1], 'JWT Payload')
// ── JWT Header ──
// Type:   JSON
//   alg:  HS256
//   typ:  JWT
//
// ── JWT Payload ──
// Type:   JSON
//   userId: usr_9f2a1c3e8b4d
//   role:   editor
//   exp:    1717203600
Poznámka:Chalk používejte pouze pro terminálový/CLI výstup — nikdy pro obsah zapisovaný do souborů, odpovědí API nebo log agregátorů. ANSI escape kódy poškodí neterminálové příjemce: log platformy (Datadog, Splunk), parsery JSON logů a prohlížeče CI logů je všechny zobrazí jako nečitelné sekvence znaků.

Dekódování velkých Base64 souborů pomocí Node.js streamů

Když Base64-kódovaný soubor překročí ~50 MB, načtení celého obsahu do paměti pomocí readFileSync() se stává problémem. Node.js streamy umožňují dekódovat data po částech — ale Base64 vyžaduje násobky 4 znaků na část (každá 4znakova skupina se dekóduje přesně na 3 bajty), aby se zabránilo chybám paddingu na hranicích částí.

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

async function streamDecodeBase64(inputPath: string, outputPath: string): Promise<void> {
  const readStream  = createReadStream(inputPath, { encoding: 'utf8', highWaterMark: 4 * 1024 * 192 })
  const writeStream = createWriteStream(outputPath)

  let buffer = ''

  await pipeline(
    readStream,
    async function* (source) {
      for await (const chunk of source) {
        buffer += (chunk as string).replace(/\s/g, '') // strip any whitespace/newlines

        // Decode only complete 4-char groups to avoid mid-stream padding issues
        const remainder = buffer.length % 4
        const safe      = buffer.slice(0, buffer.length - remainder)
        buffer          = buffer.slice(buffer.length - remainder)

        if (safe.length > 0) yield Buffer.from(safe, 'base64')
      }
      if (buffer.length > 0) yield Buffer.from(buffer, 'base64')
    },
    writeStream,
  )
}

// Decode a 200 MB video that was stored as Base64
await streamDecodeBase64('./uploads/product-demo.b64', './dist/product-demo.mp4')
console.log('Stream decode complete')
Poznámka:Velikost části musí být násobkem 4 znaků při čtení Base64 textu, aby každá část obsahovala pouze kompletní 4znakové skupiny. Příklad používá 4 × 1024 × 192 = 786 432 znaků (768 KB). Pro soubory do 50 MB je readFile() + Buffer.from(content.trim(), 'base64') jednodušší a dostatečně rychlé.

Časté chyby

Tyto čtyři chyby v JavaScriptových kódových základnách vidím opakovaně — mají tendenci zůstat skryty, dokud non-ASCII znak nebo řádkově zalomená odpověď API nedosáhne dekódovací cesty v produkci.

Chyba 1 — Použití atob() bez TextDecoder pro UTF-8 obsah

Problém: atob() vrací binární řetězec, kde každý znak je jedna surová hodnota bajtu. UTF-8 vícebajtové sekvence (cyrilice, CJK, písmena s diakritikou) se zobrazují jako nečitelné Latin-1 znaky. Řešení: zabalte výstup do TextDecoder.

Before · JavaScript
After · JavaScript
// ❌ atob() returns the raw UTF-8 bytes as a Latin-1 string
const encoded = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy'
const decoded  = atob(encoded)
console.log(decoded)
// "Алексей Р˜РІР°РЅРѕРІ"  ← wrong
// ✅ Use TextDecoder to correctly interpret the UTF-8 bytes
const encoded  = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy'
const binary   = atob(encoded)
const bytes    = Uint8Array.from(binary, ch => ch.charCodeAt(0))
const decoded  = new TextDecoder().decode(bytes)
console.log(decoded) // Алексей Иванов ✓

Chyba 2 — Předání URL-safe Base64 přímo do atob()

Problém: JWT segmenty používají - a _ místo + a /, bez paddingu. atob() může vrátit nesprávná data nebo vyhodit výjimku. Řešení: nejprve obnovte standardní znaky a přidejte padding.

Before · JavaScript
After · JavaScript
// ❌ URL-safe JWT segment passed directly — unreliable
const jwtPayload = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ'
const decoded    = atob(jwtPayload) // May produce wrong result or throw
// ✅ Restore standard Base64 chars 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)
  const bin  = atob(pad)
  const bytes = Uint8Array.from(bin, ch => ch.charCodeAt(0))
  return new TextDecoder().decode(bytes)
}
const decoded = decodeBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ')
// {"userId":"usr_9f2a1c3e"} ✓

Chyba 3 — Neodstranění konců řádků z řádkově zalomeného Base64

Problém: GitHub Contents API a MIME encodery zalamují výstup Base64 na 60–76 znacích na řádek. atob() vyhodí InvalidCharacterError na znacích \n. Řešení: před dekódováním odstraňte všechny mezery.

Before · JavaScript
After · JavaScript
// ❌ GitHub API content field contains embedded newlines
const data    = await res.json()
const decoded = atob(data.content) // ❌ throws InvalidCharacterError
// ✅ Strip newlines (and any other whitespace) before decoding
const data    = await res.json()
const clean   = data.content.replace(/\s/g, '')
const decoded = atob(clean) // ✓

Chyba 4 — Volání .toString() na dekódovaném binárním obsahu

Problém: Když jsou původní data binární (obrázky, PDF, audio), volání .toString('utf8') nahradí nerozpoznané bajtové sekvence znakem U+FFFD, čímž tiše poškodí výstup. Řešení: uchovejte výsledek jako Buffer — nepřevádějte ho na řetězec.

Before · JavaScript
After · JavaScript
// ❌ .toString('utf8') corrupts binary content
import { readFileSync, writeFileSync } from 'node:fs'
const encoded   = readFileSync('./uploads/invoice.b64', 'utf8').trim()
const corrupted = Buffer.from(encoded, 'base64').toString('utf8') // ❌
writeFileSync('./out/invoice.pdf', corrupted) // ❌ unreadable PDF
// ✅ Keep the Buffer as binary — do not convert to a string
import { readFileSync, writeFileSync } from 'node:fs'
const encoded = readFileSync('./uploads/invoice.b64', 'utf8').trim()
const binary  = Buffer.from(encoded, 'base64') // ✓ raw bytes preserved
writeFileSync('./out/invoice.pdf', binary)      // ✓ valid PDF

Metody dekódování Base64 v JavaScriptu — rychlé srovnání

MetodaUTF-8 výstupBinární výstupURL-safeProstředíVyžaduje instalaci
atob()❌ vyžaduje TextDecoder✅ binární řetězec❌ ruční obnoveníProhlížeč, Node 16+, Bun, DenoNe
TextDecoder + atob()✅ UTF-8✅ přes Uint8Array❌ ruční obnoveníProhlížeč, Node 16+, DenoNe
Buffer.from().toString()✅ utf8✅ uchovat jako Buffer✅ base64url (Node 18+)Node.js, BunNe
Uint8Array.fromBase64() (TC39)✅ přes TextDecoder✅ nativní✅ volba alphabetChrome 130+, Node 22+Ne
js-base64✅ vždy✅ Uint8Array✅ vestavěnoUniverzálnínpm install

Volte atob() pouze tehdy, když je dekódovaný obsah zaručeně ASCII text. Pro jakýkoliv uživatelsky zadaný nebo vícejazyčný text v prohlížeči použijte TextDecoder + atob(). Pro kód na straně serveru v Node.js je Buffer správná výchozí volba — zpracovává UTF-8 automaticky a zachovává binární data. Pro knihovny fungující v různých prostředích odstraní všechna okrajová případy js-base64.

Často kladené otázky

Proč atob() vrací nečitelné znaky místo čitelného textu?
atob() vrací binární řetězec, kde každý znak představuje jeden surový bajt (0–255), nikoli kódový bod Unicode. Pokud byl původní text zakódován jako UTF-8, jakýkoli znak nad U+007F — cyrilice, arabština, CJK ideografy, písmena s diakritikou — se zobrazí jako dva nebo více nečitelných Latin-1 znaků. Řešení: předejte výstup přes TextDecoder: const bytes = Uint8Array.from(atob(encoded), ch => ch.charCodeAt(0)); const text = new TextDecoder().decode(bytes). V Node.js použijte Buffer.from(encoded, 'base64').toString('utf8'), které to zvládne automaticky.
Jak dekóduji JWT token payload v JavaScriptu?
JWT má tři URL-safe Base64 segmenty oddělené tečkami: header.payload.signature. K dekódování payloadu: const [, payloadB64] = token.split('.'). V prohlížeči: obnovte standardní znaky, přidejte padding, dekódujte pomocí atob() a TextDecoder. V Node.js 18+: Buffer.from(payloadB64, 'base64url').toString('utf8'). Důležité: dekódování pouze odhalí claims — NEOVĚŘUJE podpis. Pro ověřené dekódování v produkci použijte správnou JWT knihovnu (jsonwebtoken, jose).
Jaký je rozdíl mezi atob() a Buffer.from() pro dekódování?
atob() je dostupná ve všech JavaScriptových prostředích (prohlížeč, Node.js 16+, Bun, Deno) bez importů, ale vrací binární řetězec — k převodu UTF-8 obsahu na čitelný text potřebujete TextDecoder. Buffer.from(encoded, 'base64') je pouze pro Node.js / Bun, vrací skutečný Buffer (binárně bezpečný), nativně zpracovává UTF-8 a v Node.js 18+ podporuje 'base64url'. Pro kód na serveru je Buffer jednodušší. Pro kód v prohlížeči je standardem atob() + TextDecoder. Pro knihovny fungující v různých prostředích abstrahuje rozdíl js-base64.
Jak dekóduji URL-safe Base64 v prohlížeči?
URL-safe Base64 nahrazuje + za -, / za _ a odstraňuje = padding. Obnovte je před voláním atob(): const b64 = input.replace(/-/g, '+').replace(/_/g, '/'); const padded = b64 + '==='.slice(0, (4 - b64.length % 4) % 4); const text = new TextDecoder().decode(Uint8Array.from(atob(padded), c => c.charCodeAt(0))). V Node.js 18+: Buffer.from(input, 'base64url').toString('utf8') to zvládne jedním voláním.
Jak dekóduji Base64 obsah z GitHub API v JavaScriptu?
GitHub Contents API vrací obsah souborů jako standardní Base64 se znaky nového řádku každých 60 znaků. Před dekódováním je odstraňte: const clean = data.content.replace(/\n/g, ''). V prohlížeči: new TextDecoder().decode(Uint8Array.from(atob(clean), c => c.charCodeAt(0))). V Node.js: Buffer.from(clean, 'base64').toString('utf8'). Pro binární soubory (obrázky, PDF) uchovejte Buffer bez volání .toString() — předejte ho přímo do writeFile nebo streamu odpovědi.
Mohu dekódovat Base64-kódovaný obrázek v JavaScriptu bez knihovny?
Ano. V prohlížeči: const binary = atob(encoded); const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0)); const blob = new Blob([bytes], { type: 'image/png' }); const url = URL.createObjectURL(blob). Pro src obrázku sestavte místo toho datové URI: const src = 'data:image/png;base64,' + encoded — tím se krok dekódování zcela obejde. V Node.js: Buffer.from(encoded, 'base64') následovaný writeFileSync('./out.png', buffer). Klíčové pravidlo: nikdy nevolat .toString() na dekódovaném Bufferu, když je obsah binární.

Související nástroje

Pro dekódování jedním kliknutím bez psaní kódu vložte Base64 řetězec přímo do Base64 Decoderu — okamžitě zpracovává standardní i URL-safe režimy s okamžitým výstupem ve vašem prohlížeči.

Dostupné také v:PythonGoJavaC#
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.