Base64-avkodning i JavaScript — atob() och Buffer

·Front-end & Node.js Developer·Granskad avSophie Laurent·Publicerad

Använd det kostnadsfria Base64 Decode Online direkt i webbläsaren — ingen installation krävs.

Prova Base64 Decode Online online →

När jag felsöker ett autentiseringsproblem i produktion är det första jag tar till en Base64 Decoder — JWT-payloads, webhook-signaturer och kodade konfigurationsvärden gömmer sig alla i Base64-strängar. JavaScript erbjuder två primära inbyggda sätt att base64-avkoda: atob() (webbläsare + Node.js 16+) och Buffer.from(encoded, 'base64').toString() (Node.js) — och de beter sig mycket olika när originaldata innehöll Unicode-tecken. För en snabb engångsavkodning utan att skriva kod hanterar ToolDecks Base64 Decoder det omedelbart i webbläsaren. Den här guiden täcker båda miljöerna — med fokus på Node.js 16+ och moderna webbläsare (Chrome 80+, Firefox 75+, Safari 14+) — med produktionsklara exempel: UTF-8-återställning, URL-säkra varianter, JWT-avkodning, filer, API-svar, Node.js-strömmar och de fyra misstagen som konsekvent producerar förvrängd utdata i verkliga kodbaser.

  • atob(encoded) är inbyggd i webbläsaren och tillgänglig globalt i Node.js 16+, men returnerar en binär sträng — använd TextDecoder för att återställa UTF-8-text från innehåll med tecken ovanför ASCII.
  • Buffer.from(encoded, "base64").toString("utf8") är det idiomatiska tillvägagångssättet i Node.js och hanterar UTF-8 automatiskt utan extra steg.
  • URL-säker Base64 (används i JWT) ersätter + med -, / med _ och tar bort =-padding. Återställ dessa innan du anropar atob(), eller använd Buffer.from(encoded, "base64url").toString() i Node.js 18+.
  • Ta bort blanksteg och radbrytningar innan avkodning — GitHub Contents API och många MIME-enkodare radbryter Base64-utdata vid 60–76 tecken per rad.
  • Uint8Array.prototype.fromBase64() (TC39 Stage 3) finns redan i Node.js 22+ och Chrome 130+ och kommer så småningom att förena båda miljöerna.

Vad är Base64-avkodning?

Base64-avkodning är den omvända operationen till kodning — den konverterar den 64-tecken långa ASCII-representationen tillbaka till originaldata i binär form eller text. Varje 4 Base64-tecken mappas tillbaka till exakt 3 byte. Utfyllnadstecknen = i slutet av en kodad sträng talar om för avkodaren hur många extra byte som lades till för att komplettera den sista 3-bytegruppen.

Base64 är inte kryptering — operationen är helt reversibel av vem som helst med den kodade strängen. Dess syfte är transportsäkerhet: protokoll och lagringsformat utformade för 7-bitars ASCII-text kan inte hantera godtyckliga binära byte, och Base64 överbryggar det gapet. Vanliga JavaScript-avkodningsscenarier inkluderar granskning av JWT-payloads, uppackning av Base64-kodade JSON-konfigurationer från miljövariabler, extrahering av binärt filinnehåll från REST API:er och avkodning av data-URI:er i webbläsaren.

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

atob() — Webbläsarens inbyggda avkodningsfunktion

atob() (ASCII-to-binary) har funnits i webbläsare sedan IE10 och blev en global funktion i Node.js 16.0 som en del av WinterCG-kompatibilitetsinitiativet. Den fungerar också nativt i Deno, Bun och Cloudflare Workers — ingen import krävs.

Funktionen returnerar en binär sträng: en JavaScript-sträng där varje tecken har ett kodpunktsvärde som är lika med ett råt bytevärde (0–255). Detta spelar roll: om originaldata var UTF-8-text med tecken ovanför U+007F (accenttecken, kyrilliska, CJK, emoji) är den returnerade strängen den råa bytesekvensen, inte läsbar text. Använd TextDecoder för att återställa den (täcks i nästa avsnitt).

Minimalt fungerande exempel

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

Round-trip-verifiering

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
Obs:atob() och btoa() är en del av WinterCG Minimum Common API — samma specifikation som styr Fetch, URL och crypto i miljöer utanför webbläsare. De beter sig identiskt i Node.js 16+, Bun, Deno och Cloudflare Workers.

Återställa UTF-8-text efter avkodning

Den vanligaste fallgropen med atob() är att missförstå dess returtyp. När originaltexten kodades som UTF-8 innan Base64 returnerar atob() en Latin-1 binär sträng, inte den läsbara texten:

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

Det korrekta tillvägagångssättet använder TextDecoder för att tolka de råa byten som UTF-8:

TextDecoder-metoden — säker för alla Unicode-utdata

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
Obs:I Node.js hoppa över TextDecoder-steget helt — använd Buffer.from(encoded, 'base64').toString('utf8'). Det tolkar de avkodade byten som UTF-8 automatiskt och är snabbare för stora indata.

Buffer.from() i Node.js — Komplett avkodningsguide

I Node.js är Buffer det idiomatiska API:t för alla binära operationer inklusive Base64-avkodning. Det hanterar UTF-8 nativt, returnerar en riktig Buffer (binärsäker) och stöder sedan Node.js 18 genvägen 'base64url' för URL-säkra varianter.

Avkodning av en miljövariabel-konfiguration

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

Återställa en binär fil från en .b64-fil

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

Asynkron avkodning med felhantering

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`)

Base64-avkodningsfunktioner — Parameterreferens

Snabbreferens för parametrarna i de två primära nativa avkodnings-API:erna, formaterade för användning som uppslagstabell vid skrivning eller granskning av kod.

atob(encodedData)

ParameterTypObligatoriskBeskrivning
encodedDatastringJaStandard Base64-sträng med tecknen +, /, =. URL-säkra varianter (-, _) kastar InvalidCharacterError. Blanksteg är inte tillåtet.
Returnerar: binär sträng — varje teckens kodpunkt är lika med ett råt bytevärde (0–255). Inte en Unicode-sträng; skicka genom TextDecoder för att återfå UTF-8-text.

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

ParameterTypStandardBeskrivning
inputstring | Buffer | TypedArray | ArrayBufferrequiredDen Base64-kodade strängen att avkoda, eller en buffer som innehåller kodade byte.
inputEncodingBufferEncoding"utf8"Ställ in på "base64" för standard Base64 (RFC 4648 §4), eller "base64url" för URL-säker Base64 (RFC 4648 §5, Node.js 18+).
outputEncodingstring"utf8"Kodning för .toString()-utdata. Använd "utf8" för läsbar text, "binary" för en Latin-1 binär sträng kompatibel med atob()-utdata.
startinteger0Byte-offset i den avkodade Buffern att börja läsa från. Skickas till .toString() som andra argument.
endintegerbuf.lengthByte-offset att sluta läsa vid (exklusiv). Skickas till .toString() som tredje argument.
Returnerar: Buffer från .from(). Returnerar sträng från .toString(). Behåll som Buffer (anropa inte .toString()) när det avkodade innehållet är binärt — bilder, PDF-filer, ljud.

URL-säker Base64 — Avkodning av JWT och URL-parametrar

JWT använder URL-säker Base64 (RFC 4648 §5) för alla tre segment. URL-säker Base64 ersätter + med - och / med _, och tar bort avslutande =-padding. Att skicka detta direkt till atob() utan återställning ger fel utdata eller kastar ett undantag.

Webbläsare — återställ tecken och padding innan avkodning

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+ — inbyggd 'base64url'-kodning

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

Avkodning av Base64 från filer och API-svar

I produktionskod sker Base64-avkodning oftast när externa API:er levererar innehåll i kodad form. Båda scenarierna har viktiga fallgropar kring blanksteg och binär kontra textutdata. Om du bara behöver granska ett kodat svar under felsökning kan du klistra in det direkt i Base64 Decoder — den hanterar standard- och URL-säkra lägen omedelbart.

Avkodning av innehåll från 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}`)

Avkodning av en Base64-kodad binär fil från ett API (webbläsare)

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')!)

Base64-avkodning på kommandoraden i Node.js och shell

För CI/CD-skript, felsökningssessioner eller engångsavkodningsuppgifter är shell-verktyg och Node.js-engångskommandon snabbare än ett fullständigt skript. Observera att flaggnamnet skiljer sig mellan macOS och Linux.

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"}
Obs:På macOS använder kommandot base64 flaggan -D för avkodning (stor D), medan Linux använder -d (liten d). Detta bryter CI-skript tyst — använd ett Node.js-engångskommando när målplattformen inte är garanterat Linux.

Högpresterande alternativ: js-base64

Huvudskälet att använda ett bibliotek är konsistens i olika miljöer. Om du levererar ett paket som körs i både webbläsare och Node.js utan bundler-konfiguration kräver Buffer miljödetektering och atob() kräver TextDecoder-lösningen.js-base64 (100M+ veckovisa npm-nedladdningar) hanterar båda transparent.

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

Terminalutdata med syntaxmarkering

När man skriver CLI-felsökningsverktyg eller inspektionsskript är vanlig console.log-utdata svårläst för stora JSON-payloads. chalk (det mest nedladdade npm-paketet för terminalfärgning) i kombination med Base64-avkodning producerar läsbar, överskådlig terminalutdata — användbart för JWT-inspektion, felsökning av API-svar och konfigurationsgranskning.

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
Obs:Använd chalk enbart för terminal/CLI-utdata — aldrig för innehåll som skrivs till filer, API-svar eller logginsamlare. ANSI-escape-koder förstör mottagare utanför terminaler: loggplattformar (Datadog, Splunk), JSON-loggparsers och CI-loggvisare visar alla dem som oläsbara teckensekvenser.

Avkoda stora Base64-filer med Node.js-strömmar

När en Base64-kodad fil överstiger ~50 MB blir det ett problem att läsa in den helt i minnet med readFileSync(). Node.js-strömmar låter dig avkoda data i bitar — men Base64 kräver multipler av 4 tecken per bit (varje 4-teckensgrupp avkodar till exakt 3 byte) för att undvika padding-fel vid bitgränser.

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')
Obs:Bitstorlek måste vara en multipel av 4 tecken vid läsning av Base64-text, så att varje bit bara innehåller kompletta 4-teckensgrupper. Exemplet använder 4 × 1024 × 192 = 786 432 tecken (768 KB). För filer under 50 MB är readFile() + Buffer.from(content.trim(), 'base64') enklare och tillräckligt snabbt.

Vanliga misstag

Dessa fyra misstag i JavaScript-kodbaser ser jag upprepade gånger — de tenderar att förbli dolda tills ett icke-ASCII-tecken eller ett radbrutet API-svar når avkodningssökvägen i produktion.

Misstag 1 — Använda atob() utan TextDecoder för UTF-8-innehåll

Problem: atob() returnerar en binär sträng där varje tecken är ett råt bytevärde. UTF-8 flerbytesekvenser (kyrilliska, CJK, accenttecken) visas som förvrängda Latin-1-tecken. Lösning: omslut utdata i 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) // Алексей Иванов ✓

Misstag 2 — Skicka URL-säker Base64 direkt till atob()

Problem: JWT-segment använder - och _ istället för + och /, utan padding. atob() kan returnera fel data eller kasta undantag. Lösning: återställ standardtecken och lägg till padding först.

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"} ✓

Misstag 3 — Inte ta bort radbrytningar från radbruten Base64

Problem: GitHub Contents API och MIME-enkodare radbryter Base64-utdata vid 60–76 tecken per rad. atob() kastar InvalidCharacterError för \n-tecken. Lösning: ta bort alla blanksteg innan avkodning.

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) // ✓

Misstag 4 — Anropa .toString() på avkodat binärt innehåll

Problem: När originaldata är binärt (bilder, PDF-filer, ljud) ersätter .toString('utf8') okända bytesekvenser med U+FFFD, vilket tyst korrumperar utdata. Lösning: behåll resultatet som Buffer — konvertera inte till en sträng.

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

JavaScript Base64-avkodningsmetoder — snabb jämförelse

MetodUTF-8-utdataBinär utdataURL-säkerMiljöerKräver installation
atob()❌ kräver TextDecoder✅ binär sträng❌ manuell återställningWebbläsare, Node 16+, Bun, DenoNej
TextDecoder + atob()✅ UTF-8✅ via Uint8Array❌ manuell återställningWebbläsare, Node 16+, DenoNej
Buffer.from().toString()✅ utf8✅ behåll som Buffer✅ base64url (Node 18+)Node.js, BunNej
Uint8Array.fromBase64() (TC39)✅ via TextDecoder✅ nativt✅ alphabet-alternativChrome 130+, Node 22+Nej
js-base64✅ alltid✅ Uint8Array✅ inbyggtUniverselltnpm install

Välj atob() bara när det avkodade innehållet är garanterat ASCII-text. För användarinmatad eller flerspråkig text i webbläsaren, använd TextDecoder + atob(). För serversideskod i Node.js är Buffer rätt standard — den hanterar UTF-8 automatiskt och bevarar binärdata. För bibliotek i flera miljöer tar js-base64 bort alla specialfall.

Vanliga frågor

Varför returnerar atob() förvrängda tecken istället för läsbar text?
atob() returnerar en binär sträng där varje tecken representerar en råt byte (0–255), inte en Unicode-kodpunkt. Om originaltexten kodades som UTF-8 visas tecken ovanför U+007F — kyrilliska, arabiska, CJK-ideogram, accenttecken — som två eller flera förvrängda Latin-1-tecken. Lösningen: skicka utdata genom TextDecoder: const bytes = Uint8Array.from(atob(encoded), ch => ch.charCodeAt(0)); const text = new TextDecoder().decode(bytes). I Node.js använder du Buffer.from(encoded, 'base64').toString('utf8') som hanterar detta automatiskt.
Hur avkodar jag en JWT-token-payload i JavaScript?
En JWT har tre URL-säkra Base64-segment separerade av punkter: header.payload.signature. För att avkoda payloaden: const [, payloadB64] = token.split('.'). I webbläsaren: återställ standardtecken, lägg till padding, avkoda med atob() och TextDecoder. I Node.js 18+: Buffer.from(payloadB64, 'base64url').toString('utf8'). Viktigt: avkodning avslöjar bara claims — den VERIFIERAR INTE signaturen. Använd ett ordentligt JWT-bibliotek (jsonwebtoken, jose) för verifierad avkodning i produktion.
Vad är skillnaden mellan atob() och Buffer.from() för avkodning?
atob() är tillgänglig i alla JavaScript-miljöer (webbläsare, Node.js 16+, Bun, Deno) utan importer, men returnerar en binär sträng — du behöver TextDecoder för att konvertera UTF-8-innehåll till läsbar text. Buffer.from(encoded, 'base64') är bara för Node.js / Bun, returnerar en riktig Buffer (binärsäker), hanterar UTF-8 nativt och stöder 'base64url' i Node.js 18+. För serversidekod är Buffer enklare. För webbläsarkod är atob() + TextDecoder standard. För bibliotek i flera miljöer abstraherar js-base64 skillnaden.
Hur avkodar jag URL-säker Base64 i webbläsaren?
URL-säker Base64 ersätter + med -, / med _ och tar bort =-padding. Återställ dem innan du anropar 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))). I Node.js 18+: Buffer.from(input, 'base64url').toString('utf8') hanterar det i ett anrop.
Hur avkodar jag Base64-innehåll från GitHub API i JavaScript?
GitHub Contents API returnerar filinnehåll som standard Base64 med radmatningstecken var 60:e tecken. Ta bort dem innan avkodning: const clean = data.content.replace(/\n/g, ''). I webbläsaren: new TextDecoder().decode(Uint8Array.from(atob(clean), c => c.charCodeAt(0))). I Node.js: Buffer.from(clean, 'base64').toString('utf8'). För binära filer (bilder, PDF) behåll Buffer utan att anropa .toString() — skicka det direkt till writeFile eller svarsströmmen.
Kan jag avkoda en Base64-kodad bild i JavaScript utan ett bibliotek?
Ja. I webbläsaren: 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). För img src, bygg en data-URI istället: const src = 'data:image/png;base64,' + encoded — detta hoppar helt över avkodningssteget. I Node.js: Buffer.from(encoded, 'base64') följt av writeFileSync('./out.png', buffer). Nyckelregeln: anropa aldrig .toString() på den avkodade Buffer om innehållet är binärt.

Relaterade verktyg

För enklicksavkodning utan att skriva kod, klistra in din Base64-sträng direkt i Base64 Decoder — den hanterar standard- och URL-säkra lägen med omedelbar utdata i din webbläsare.

Finns även på: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 LaurentTeknisk granskare

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.