Base64 i JavaScript: btoa(), Buffer och Unicode

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

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

Prova Base64 Encode Online online →

När du bäddar in en bild i en CSS data URI, skickar inloggningsuppgifter i ett HTTP Authorization-huvud eller lagrar ett binärt certifikat i en miljövariabel behöver du koda data i Base64 tillförlitligt i JavaScript — både i webbläsaren och i Node.js. JavaScript tillhandahåller två distinkta inbyggda API:er:btoa() för webbläsarmiljöer (finns också i Node.js 16+) och Buffer.from() för Node.js — var och en med olika begränsningar kring Unicode, binärdata och URL-säkerhet. För snabb engångskodning utan att skriva någon kod ToolDeck's Base64 Encoder hanterar det direkt i webbläsaren. Den här guiden täcker båda miljöerna med produktionsklara exempel: Unicode-hantering, URL-säkra varianter, fil- och API-svarscodning, CLI-användning och de fyra misstagen som konsekvent orsakar buggar i riktiga kodbaser.

  • btoa() är inbyggd i webbläsaren och tillgänglig i Node.js 16+ globalt, men accepterar bara Latin-1 (kodpunkter 0–255) — Unicode-indata kastar ett DOMException
  • Buffer.from(text, "utf8").toString("base64") är Node.js-ekvivalenten och hanterar Unicode nativt utan extra steg
  • URL-säker Base64 ersätter + → -, / → _ och tar bort = padding — använd Buffer.from().toString("base64url") i Node.js 18+ för en one-liner
  • För binärdata (ArrayBuffer, Uint8Array, filer) använd Buffer i Node.js eller arrayBuffer() + Uint8Array i webbläsaren — aldrig response.text()
  • Uint8Array.prototype.toBase64() (TC39 Stage 3) finns redan i Node.js 22+ och Chrome 130+ och kommer att förena båda miljöerna

Vad är Base64-kodning?

Base64 konverterar godtyckliga binärdata till en sträng uppbyggd av 64 utskrivbara ASCII-tecken: A–Z, a–z, 0–9, + och /. Varje 3 bytes indata mappas till exakt 4 Base64-tecken; om indatalängden inte är en multipel av 3 läggs ett eller två = utfyllnadstecken till. Den kodade utdata är alltid ungefär 33% större än originalet.

Base64 är inte kryptering — det ger ingen konfidentialitet. Vem som helst med den kodade strängen kan avkoda den med ett funktionsanrop. Syftet är transportsäkerhet: många protokoll och lagringsformat konstruerades för 7-bitars ASCII-text och kan inte hantera godtyckliga binära bytes. Base64 överbryggar det gapet. Vanliga användningsfall i JavaScript inkluderar data URI:er för inlining av tillgångar, HTTP Basic Auth-huvuden, JWT-tokensegment, e-post MIME-bilagor och lagring av binära blobbar i JSON API:er.

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

btoa() — webbläsarens inbyggda kodningsfunktion

btoa() (binary-to-ASCII) har funnits i webbläsare sedan IE10 och blev en global funktion i Node.js 16.0 som en del av WinterCG-initiativet. Den fungerar även nativt i Deno, Bun och Cloudflare Workers. Ingen import behövs.

Funktionen tar ett enda strängargument och returnerar dess Base64-kodade form. Den symmetriska motparten atob() (ASCII-to-binary) avkodar den tillbaka. Båda är synkrona och körs med konstant minne relativt till indatastorleken.

Minimalt fungerande exempel

JavaScript (browser / Node.js 16+)
// Koda ett API-inloggningspar för ett HTTP Basic Auth-huvud
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=

Avkodning med atob()

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

Hantera Unicode och icke-ASCII-tecken

Den vanligaste fällan med btoa() är dess strikta Latin-1-gräns. Varje tecken med en kodpunkt över U+00FF orsakar omedelbart ett undantag:

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

Det korrekta tillvägagångssättet är att koda strängen till UTF-8-bytes först, och sedan Base64-koda dessa bytes. JavaScript tillhandahåller TextEncoder exakt för detta ändamål:

TextEncoder-metoden — säker för all Unicode-indata

JavaScript (browser + Node.js 16+)
// Hjälpfunktioner för Unicode-säker 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)
}

// Fungerar med vilket språk eller skriftsystem som helst
const orderNote = 'Bekräftat: Erik Lindqvist — lager i Göteborg, antal: 250'
const encoded   = toBase64(orderNote)
const decoded   = fromBase64(encoded)

console.log(encoded)
// QmVrcuRmdGF0OiBFcmlrIExpbmRxdmlzdCDigJMgbGFnZXIgaSBHw7Z0ZWJvcmcsIGFudGFsOiAyNTA=

console.log(decoded === orderNote) // true
Obs:Om du redan är i Node.js, hoppa över TextEncoder-omvägen helt — använd Buffer.from(text, 'utf8').toString('base64'). Det hanterar Unicode nativt och är snabbare för stora strängar.

Buffer.from() i Node.js — komplett guide med exempel

I Node.js är Buffer det idiomatiska API:et för alla binärdataoperationer, inklusive kodningskonverteringar. Det föregår TextEncoder med år och förblir det föredragna valet för server-side kod. Viktiga fördelar jämfört med btoa(): nativt UTF-8-stöd, hantering av binärdata och genvägen för 'base64url'-kodning tillgänglig sedan Node.js 18.

Grundläggande textkodning och avkodning

Node.js
// Koda ett serverkonfigurationsobjekt för lagring i en miljövariabel
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...

// Avkoda tillbaka
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

Koda binärfiler från disk

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

// Läs ett TLS-certifikat och koda det för inbäddning i en konfigurationsfil
const certPem     = readFileSync(join(process.cwd(), 'ssl', 'server.crt'))
const certBase64  = certPem.toString('base64')

// Spara som en enradsträng — lämplig för miljövariabler eller JSON-konfigurationer
writeFileSync('./dist/cert.b64', certBase64, 'utf8')

console.log(`Certifikat kodat: ${certBase64.length} tecken`)
// Certifikat kodat: 2856 tecken

// Återställ det binära certifikatet från det kodade värdet
const restored = Buffer.from(certBase64, 'base64')
console.log(restored.equals(certPem)) // true

Asynkron filkodning med felhantering

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(`Filen hittades inte: ${filePath}`)
    if (code === 'EACCES') throw new Error(`Åtkomst nekad: ${filePath}`)
    throw err
  }
}

// Koda en PDF för en e-postbilaga
const reportBase64 = await encodeFileToBase64('./reports/q1-financials.pdf')

const emailPayload = {
  to:          'finance-team@company.internal',
  subject:     'Ekonomisk rapport Q1',
  attachments: [{
    filename:    'q1-financials.pdf',
    content:     reportBase64,
    encoding:    'base64',
    contentType: 'application/pdf',
  }],
}

console.log(`Bilaga: ${reportBase64.length} tecken`)

JavaScript Base64-funktioner — parameterreferens

Till skillnad från Pythons base64-modul har JavaScript ingen enda enhetlig Base64-funktion. API:et beror på målmiljön. Här är den kompletta referensen för alla nativa metoder:

FunktionIndatatypUnicodeURL-säkerTillgänglig i
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+

Signaturen Buffer.from(src, enc).toString(enc) accepterar flera kodningsvärden relevanta för Base64:

"base64"
Standard Base64 (RFC 4648 §4). Använder + och / med = utfyllnad.
"base64url"
URL-säker Base64 (RFC 4648 §5, Node.js 18+). Använder - och _ utan utfyllnad.
"utf8"
Standard för strängkällor. Använd när källan är läsbar text.
"binary"
Latin-1 / ISO-8859-1. Används när källan är en rå binärsträng (t.ex. från atob()).

URL-säker Base64 — kodning för JWT:er, URL:er och filnamn

Standard Base64 använder + och /, som är reserverade i URL:er — + avkodas som ett mellanslag i frågesträngar, och / är en sökvägsavgränsare. JWT:er, URL-parametrar, filnamn och cookie-värden kräver den URL-säkra varianten: +-, /_, avslutande = tas bort.

Webbläsare — manuell teckenbyte

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

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

Koda filer och API-svar i JavaScript

I produktionskod tillämpas Base64-kodning oftast på filer som skickas och på svar från externa API:er som levererar binärt innehåll. Mönstren skiljer sig mellan webbläsare och Node.js, och binärdata kräver särskild omsorg.

Webbläsare — koda en fil från ett input-element

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

    // Visa bilden inline
    const img   = document.getElementById('preview') as HTMLImageElement
    img.src     = dataUri
    img.hidden  = false

    console.log(`Kodad ${file.name} (${file.size} bytes) → ${encoded.length} Base64-tecken`)
  } catch (err) {
    console.error('Kodning misslyckades:', err)
  }
})

Hämta Base64-kodat binärdata från ett 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}`)

När du bara behöver inspektera ett kodat svar under API-felsökning utan att sätta upp ett skript, klistra in Base64-värdet direkt i Base64 Encoder — den avkodar också med omedelbar utdata. Användbart för att inspektera GitHub API-svar, JWT-payloads och webhook-signaturer.

Base64-kodning via kommandoraden i Node.js och Shell

För CI/CD-skript, Makefile-mål eller engångsfelsökning behöver du sällan ett fullständigt skript. Både systemverktyg och Node.js-one-liners täcker de flesta fall plattformsoberoende.

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=="
Obs:På macOS bryter base64 utdata efter 76 tecken som standard. Det bryter nedströmsanalys. Lägg alltid till -b 0 (macOS) eller --wrap=0 (Linux) när du behöver ett enkelt radsresultat — till exempel när du skriver till en miljövariabel eller ett konfigurationsfält.

Högpresterande alternativ: js-base64

De inbyggda API:erna räcker för de flesta användningsfall. Huvudorsaken till att använda ett bibliotek är konsekvens mellan miljöer: om du levererar ett paket som körs i både webbläsare och Node.js kräver Buffer antingen miljödetektering eller bundelarkonfiguration, medan btoa() kräver Unicode-omvägen. js-base64 (100M+ veckliga npm-nedladdningar) hanterar båda transparent.

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

Under huven använder js-base64 nativ Buffer när tillgänglig och faller tillbaka till en ren-JS-implementering i webbläsaren. Det är 2–3× snabbare än TextEncoder+btoa-metoden för stora Unicode-strängar, och det symmetriska API:et (toBase64 / fromBase64) eliminerar den mentala bördan att komma ihåg i vilken riktning btoa och atob går.

Koda stora binärfiler med Node.js-strömmar

När du behöver koda filer större än ~50 MB blir det ett problem att ladda hela filen i minnet med readFileSync(). Node.js-strömmar låter dig bearbeta data i bitar — men Base64-kodning har en begränsning: du måste mata kodaren med multiplar av 3 bytes för att undvika felaktig utfyllnad vid bitgränser.

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('Strömkodning klar')
Obs:Bitstorlek måste vara en multipel av 3 bytes för att undvika falsk = utfyllnad i mitten av utdata. Exemplet använder 3 * 1024 * 256 = 786 432 bytes (768 KB) — justera highWaterMark baserat på din minnesbudget. För filer under 50 MB är readFile() + Buffer.toString('base64') enklare och tillräckligt snabbt.

Vanliga misstag

Jag har granskat många JavaScript-kodbaser med Base64-kodning, och dessa fyra misstag förekommer konsekvent — ofta oupptäckta tills ett icke-ASCII-tecken eller en binärfil når kodningssökvägen i produktion.

Misstag 1 — Skicka Unicode direkt till btoa()

Problem: btoa() accepterar bara tecken med kodpunkter 0–255. Tecken som ñ, emoji eller CJK-ideogram orsakar ett omedelbart DOMException. Lösning: koda med TextEncoder först, eller använd Buffer.from(text, 'utf8').toString('base64') i Node.js.

Before · JavaScript
After · JavaScript
// ❌ DOMException: The string to be encoded contains
//    characters outside of the Latin1 range
const username = 'Erik Lindqvist'
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('Erik Lindqvist')
// RXJpayBMaW5kcXZpc3Q=

Misstag 2 — Glömma att återställa utfyllnad före atob()

Problem: URL-säker Base64 tar bort =-utfyllnaden. Att skicka den urtagna strängen direkt till atob() ger felaktig utdata eller kastar ett undantag beroende på stränglängden. Lösning: återställ + och / och lägg tillbaka rätt mängd utfyllnad innan du anropar 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"}

Misstag 3 — Sammanfoga kodade bitar istället för råa buffertar

Problem: Varje anrop till btoa() eller .toString('base64') lägger till sin egen utfyllnad. Att sammanfoga två utfyllda Base64-strängar ger ogiltig utdata eftersom utfyllnad bara hör hemma i slutet. Lösning: sammanfoga rådata före kodning.

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

Misstag 4 — Använda response.text() för att läsa binärt API-data före kodning

Problem: response.text() tolkar råbytes som UTF-8 och ersätter okända bytesekvenser med ersättningstecknet U+FFFD. Allt binärt innehåll — bilder, PDF:er, ljud — skadas tyst innan det når btoa(). Lösning: använd response.arrayBuffer() för att få råbytes.

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

JavaScript Base64-metoder — snabb jämförelse

MetodUnicodeBinärdataURL-säkerMiljöerKräver installation
btoa() / atob()❌ Latin-1❌ workaround needed❌ manual replaceBrowser, Node 16+, Bun, DenoNej
TextEncoder + btoa()✅ UTF-8✅ via Uint8Array❌ manual replaceBrowser, Node 16+, DenoNej
Buffer.from().toString()✅ utf8✅ native✅ base64url (Node 18+)Node.js, BunNej
Uint8Array.toBase64() (TC39)✅ binary✅ native✅ alphabet optionChrome 130+, Node 22+Nej
js-base64✅ always✅ Uint8Array✅ built-inUniversalnpm install

Välj btoa() bara när indata bevisligen är ASCII-only — hex-digestar, numeriska ID:n eller förvaliderade Latin-1-strängar. För användarlevererad text i en webbläsare, använd TextEncoder + btoa(). För all Node.js server-side kod är Buffer rätt standard. För bibliotek som behöver köra i båda miljöerna utan bundelarkonfiguration eliminerar js-base64 alla kantfall.

Vanliga frågor

Varför kastar btoa() "InvalidCharacterError" på min sträng?
btoa() accepterar bara tecken med kodpunkter i intervallet 0–255 (Latin-1 / ISO-8859-1). Alla tecken ovanför U+00FF — inklusive de flesta kyrilliska, arabiska, CJK-ideogram och många emoji — orsakar ett DOMException. Lösningen beror på din miljö: i webbläsaren kodar du till UTF-8-bytes med TextEncoder, konverterar varje byte till ett tecken med String.fromCharCode() och anropar sedan btoa(). I Node.js använder du Buffer.from(text, 'utf8').toString('base64') som hanterar Unicode nativt.
Är btoa() tillgänglig i Node.js utan någon import?
Ja, sedan Node.js 16.0. Både btoa() och atob() är registrerade som globala funktioner — ingen import krävs. De beter sig identiskt med sina webbläsarmotparter, inklusive Latin-1-begränsningen. För Node.js-serverkod föredras Buffer.from() fortfarande framför btoa() eftersom det hanterar UTF-8 nativt, stöder binärdata utan omvägar och har alternativet 'base64url'-kodning lagt till i Node.js 18.
Vad är skillnaden mellan standard Base64 och URL-säker Base64?
Standard Base64 (RFC 4648 §4) använder + för värde 62, / för värde 63 och = för utfyllnad. Dessa tecken har speciell betydelse i URL:er: + tolkas som mellanslag i frågesträngar, och / är en sökvägsavgränsare. URL-säker Base64 (RFC 4648 §5) ersätter - mot + och _ mot /, och utelämnar vanligtvis = utfyllnaden helt. JWT:er använder URL-säker Base64 för alla tre segment. I Node.js 18+ producerar Buffer.from(text).toString('base64url') det URL-säkra formatet direkt.
Hur kodar jag en bild till Base64 för en CSS data URI i JavaScript?
I en webbläsare: använd file.arrayBuffer() för att läsa binärdata, konvertera till Uint8Array och anropa sedan btoa(Array.from(bytes, b => String.fromCharCode(b)).join('')). Bygg data URI som 'data:' + file.type + ';base64,' + encoded. I Node.js: const encoded = fs.readFileSync('./image.png').toString('base64') och lägg till MIME-typen. För SVG-filer kan du ofta hoppa över Base64 helt och använda en URL-kodad data URI istället, vilket är mer läsbart och något mindre.
Kan jag Base64-koda och avkoda utan något npm-bibliotek i webbläsaren?
Ja. För ASCII-indata fungerar btoa() och atob() direkt. För Unicode ger paret TextEncoder / TextDecoder dig den kompletta verktygslådan — båda är inbyggda i alla moderna webbläsare och Node.js 16+. Det enda fallet där ett bibliotek verkligen tillför värde är konsekvens mellan miljöer: om du skriver en hjälpfunktion som måste fungera identiskt i både webbläsare och Node.js utan bundelarkonfiguration tar js-base64 bort miljödetekteringslogiken.
Hur avkodar jag Base64-innehåll från GitHub API?
GitHub Contents API returnerar filinnehåll som Base64 med inbäddade radmatningstecken (API:et bryter utdata vid 60 tecken). Ta bort dem före avkodning: const clean = data.content.replace(/\n/g, ''); const text = atob(clean);. I Node.js: const text = Buffer.from(data.content.replace(/\n/g, ''), 'base64').toString('utf8');. GitHub använder alltid standard Base64 (inte URL-säker), så ingen + → - eller / → _ substitution behövs.

Relaterade verktyg

För enklicks-kodning eller avkodning utan att skriva kod, klistra in din sträng eller binärdata direkt i Base64 Encoder — den hanterar standard- och URL-säkra lägen direkt i din webbläsare.

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