Base64 dyker upp överallt när du börjar leta — JWT-tokens, data-URI:er, e-postbilagor,
API-nyttolaster med binärfiler. Kodningen i sig definieras i
RFC 4648
och är dödlätt i konceptet: ta godtyckliga bytes och representera dem med bara 64 utskrivbara
ASCII-tecken. Det som snubblar folk är implementationen i JavaScript — olika API:er i
webbläsare vs Node.js, Unicode-fällan som gör att btoa() kastar undantag, och
URL-säker variant som JWT:er beror på. Den här guiden täcker allt med fungerande kod.
btoa() och atob() i webbläsaren
Webbläsaren har länge haft
btoa()
och
atob().
Namnen är förvirrande (binary to ASCII och tillbaka), men användningen är
enkel för enkla strängar:
// Encode a plain ASCII string
const encoded = btoa('hello world');
console.log(encoded); // "aGVsbG8gd29ybGQ="
// Decode it back
const decoded = atob('aGVsbG8gd29ybGQ=');
console.log(decoded); // "hello world"
// A more realistic example — encoding a simple auth token
const credentials = 'apiuser:s3cr3tkey';
const basicAuth = 'Basic ' + btoa(credentials);
// "Basic YXBpdXNlcjpzM2NyM3RrZXk="
// This is exactly what HTTP Basic Authentication usesbtoa() hanterar bara strängar där
varje tecken har en kodpunkt ≤ 255 (Latin-1-området). Skicka en sträng med
ett emoji eller ett icke-latinskt tecken och den kastar InvalidCharacterError omedelbart.
Det här är ett av de vanligaste Base64-buggarna i webbläsarkod.// ❌ This throws — emoji is outside Latin-1
btoa('Hello 🌍');
// Uncaught DOMException: Failed to execute 'btoa' on 'Window':
// The string to be encoded contains characters outside of the Latin1 range.
// ❌ This also throws — any non-ASCII character will do it
btoa('café');
// Uncaught DOMException: ...Hantera Unicode säkert i webbläsaren
Lösningen är att först koda strängen till UTF-8-bytes och sedan Base64-koda de bytes.
Det klassiska tillvägagångssättet använder encodeURIComponent och ett procentavkodningstrick. Det moderna
tillvägagångssättet använder TextEncoder, som är
tillgänglig i alla moderna webbläsare
och Node.js 11+:
// ✅ Unicode-safe encode using TextEncoder
function encodeBase64(str) {
const bytes = new TextEncoder().encode(str); // UTF-8 byte array
const binString = Array.from(bytes, byte =>
String.fromCodePoint(byte)
).join('');
return btoa(binString);
}
// ✅ Unicode-safe decode using TextDecoder
function decodeBase64(base64Str) {
const binString = atob(base64Str);
const bytes = Uint8Array.from(binString, char =>
char.codePointAt(0)
);
return new TextDecoder().decode(bytes);
}
// Now emojis and international text work fine
console.log(encodeBase64('Hello 🌍')); // "SGVsbG8g8J+MjQ=="
console.log(decodeBase64('SGVsbG8g8J+MjQ==')); // "Hello 🌍"
console.log(encodeBase64('Héllo café')); // "SMOpbGxvIGNhZsOp"
console.log(decodeBase64('SMOpbGxvIGNhZsOp')); // "Héllo café"Spara de här två hjälpfunktionerna någonstans i din kodbas och glöm att det nakna
btoa() existerar. Paret TextEncoder/TextDecoder är
rätt verktyg för allt utöver ren ASCII. Du kan prova det just nu med verktyget
Base64 Encoder.
Buffer.from() i Node.js
Node.js har ett eget API för detta via Buffer-klassen, som hanterar kodning/avkodning renare. Det finns ingen Unicode-fallgrop här eftersom du explicit anger indatakodningen:
// Encode string → Base64
const encoded = Buffer.from('Hello 🌍', 'utf8').toString('base64');
console.log(encoded); // "SGVsbG8g8J+MjQ=="
// Decode Base64 → string
const decoded = Buffer.from('SGVsbG8g8J+MjQ==', 'base64').toString('utf8');
console.log(decoded); // "Hello 🌍"
// Practical example — encoding a JSON payload to embed in a config file
const config = {
apiKey: 'sk-prod-abc123',
projectId: 'proj_x9f2k',
region: 'us-east-1'
};
const encodedConfig = Buffer.from(JSON.stringify(config), 'utf8').toString('base64');
// eyJhcGlLZXkiOiJzay1wcm9kLWFiYzEyMyIsInByb2plY3RJZCI6InByb2pfeDlmMmsiLCJyZWdpb24iOiJ1cy1lYXN0LTEifQ==
// Decode and parse it back
const decodedConfig = JSON.parse(
Buffer.from(encodedConfig, 'base64').toString('utf8')
);
console.log(decodedConfig.region); // "us-east-1"Observera att btoa() och atob() även är tillgängliga i Node.js 16+
som globala variabler (för webbläsarkompatibilitet), men Buffer-API:et är mer idiomatiskt i
Node.js och har funnits sedan
Node.js v0.1.
För JSON-specifik kodning är verktyget JSON to Base64 praktiskt
för snabba manuella konverteringar.
URL-säker Base64 — vad JWT:er faktiskt använder
Standard-Base64 använder + och / i sitt alfabet. Båda de
tecknen är speciella i URL:er — + betyder ett mellanslag i frågesträngar, och /
är en sökvägsavgränsare. När du behöver Base64 i en URL eller som ett JWT-segment använder du URL-säker
variant: ersätt + med - och / med _,
ta sedan bort =-utfyllnaden. Detta standardiseras i
RFC 4648 §5
och är vad varje JWT-bibliotek använder internt:
// Convert standard Base64 to URL-safe Base64
function toBase64Url(base64Str) {
return base64Str
.replace(/+/g, '-')
.replace(///g, '_')
.replace(/=+$/, ''); // strip padding
}
// Convert URL-safe Base64 back to standard Base64
function fromBase64Url(base64UrlStr) {
// Restore padding — length must be a multiple of 4
const padded = base64UrlStr + '==='.slice((base64UrlStr.length + 3) % 4);
return padded
.replace(/-/g, '+')
.replace(/_/g, '/');
}
// Encode a string to URL-safe Base64
function encodeBase64Url(str) {
return toBase64Url(btoa(str));
}
// Decode URL-safe Base64 to a string
function decodeBase64Url(str) {
return atob(fromBase64Url(str));
}
// Example: manually inspect a JWT payload
const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjQyLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3MTM0MDAwMDB9.signature';
const [header, payload] = jwt.split('.');
console.log(decodeBase64Url(header));
// {"alg":"HS256","typ":"JWT"}
console.log(decodeBase64Url(payload));
// {"userId":42,"role":"admin","iat":1713400000}Det är därför du ser Base64-strängar som
eyJhbGciOiJIUzI1NiJ9 i JWT:er — ingen utfyllnad, bindestreck istället för plustecken.
När du skickar kodad data som en URL-frågeparameter, använd alltid URL-säker variant för att
undvika trasiga URL:er. Verktyget Base64 Decoder hanterar både
standard och URL-säker Base64 automatiskt.
Koda en fil med FileReader API
En vanlig webbläsaruppgift: användaren väljer en bild eller ett dokument, och du behöver skicka det
till ett API som Base64.
FileReader API
har readAsDataURL() för exakt detta — det ger dig en komplett data-URI med
MIME-typen inkluderad:
// Wrap FileReader in a Promise for easier async usage
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
// result is "data:image/png;base64,iVBORw0KGgo..."
// Strip the data URI prefix to get just the Base64 string
const base64 = reader.result.split(',')[1];
resolve(base64);
};
reader.onerror = () => reject(new Error('Failed to read file'));
reader.readAsDataURL(file);
});
}
// Hook it up to a file input
const fileInput = document.getElementById('avatarUpload');
fileInput.addEventListener('change', async (event) => {
const file = event.target.files[0];
if (!file) return;
try {
const base64 = await fileToBase64(file);
console.log(`File size: ${file.size} bytes`);
console.log(`Base64 length: ${base64.length} chars`);
// Send to your API
await fetch('/api/users/42/avatar', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image: base64, mimeType: file.type })
});
} catch (err) {
console.error('Upload failed:', err.message);
}
});Om du behöver den fullständiga data-URI:n (inklusive MIME-typsprefixet) istället för bara
rå Base64, hoppa över .split(',')[1] och använd reader.result direkt.
För masskonvertering av filer hanterar verktyget Image to Base64
bilder utan att skriva någon kod.
Koda binärdata och Uint8Arrays
Ibland börjar du inte från en sträng eller en fil — du har råa bytes från en
WebCrypto-operation, en canvas-export eller en WebAssembly-modul. Här är hur man går från en
Uint8Array till Base64 och tillbaka i båda miljöerna:
// --- Browser ---
// Uint8Array → Base64 (browser)
function uint8ToBase64(bytes) {
const binString = Array.from(bytes, byte =>
String.fromCodePoint(byte)
).join('');
return btoa(binString);
}
// Base64 → Uint8Array (browser)
function base64ToUint8(base64Str) {
const binString = atob(base64Str);
return Uint8Array.from(binString, char => char.codePointAt(0));
}
// Example: export a canvas as raw PNG bytes → Base64
const canvas = document.getElementById('myCanvas');
canvas.toBlob(blob => {
blob.arrayBuffer().then(buffer => {
const bytes = new Uint8Array(buffer);
const encoded = uint8ToBase64(bytes);
console.log('PNG as Base64:', encoded.slice(0, 40) + '...');
});
}, 'image/png');
// --- Node.js ---
// Uint8Array / Buffer → Base64 (Node.js)
function uint8ToBase64Node(bytes) {
return Buffer.from(bytes).toString('base64');
}
// Base64 → Buffer (Node.js)
function base64ToBufferNode(base64Str) {
return Buffer.from(base64Str, 'base64');
}
// Example: hash a password and encode the result
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('mySecretPassword').digest();
// hash is a Buffer (which extends Uint8Array)
console.log(hash.toString('base64'));
// "XohImNooBHFR0OVvjcYpJ3NgxxxxxxxxxxxxxA=="Bädda in bilder som data-URI:er
En av de mest praktiska användningarna av Base64 i webbutveckling är att bädda in bilder direkt i HTML eller CSS, vilket eliminerar en HTTP-förfrågan. Du har förmodligen sett data-URI:er i inline-SVG:er eller e-postmallar. Här är mönstret:
<!-- Inline image in HTML — no separate network request -->
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
alt="1x1 transparent pixel"
width="1"
height="1"
/>/* Inline background image in CSS — commonly used for small icons and loading spinners */
.spinner {
width: 32px;
height: 32px;
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDJhMTAgMTAgMCAxIDAgMCAyMCAxMCAxMCAwIDAgMCAwLTIweiIvPjwvc3ZnPg==");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}// Generate a data URI from a fetched image (Node.js)
const fs = require('fs');
const path = require('path');
function imageFileToDataUri(filePath) {
const ext = path.extname(filePath).slice(1).toLowerCase();
const mimeMap = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg',
gif: 'image/gif', svg: 'image/svg+xml', webp: 'image/webp' };
const mimeType = mimeMap[ext] ?? 'application/octet-stream';
const fileData = fs.readFileSync(filePath);
const base64 = fileData.toString('base64');
return `data:${mimeType};base64,${base64}`;
}
const dataUri = imageFileToDataUri('./logo.png');
// "data:image/png;base64,iVBORw0KGgo..."
// Drop this into an <img src> or CSS background-imageEn kompakt nyttomodul för båda miljöerna
Istället för att sprida btoa()-anrop i din kodbas är det värt att ha
en enda nyttomodul som täcker Unicode, URL-säkra varianter och fungerar i både
webbläsare och Node.js. Här är en som gör allt det:
// base64.js — drop into any project
const isNode = typeof process !== 'undefined' && process.versions?.node;
export function encode(str) {
if (isNode) {
return Buffer.from(str, 'utf8').toString('base64');
}
// Browser: encode to UTF-8 bytes first, then Base64
const bytes = new TextEncoder().encode(str);
const binString = Array.from(bytes, b => String.fromCodePoint(b)).join('');
return btoa(binString);
}
export function decode(base64Str) {
if (isNode) {
return Buffer.from(base64Str, 'base64').toString('utf8');
}
// Browser: Base64 → bytes → UTF-8 string
const binString = atob(base64Str);
const bytes = Uint8Array.from(binString, c => c.codePointAt(0));
return new TextDecoder().decode(bytes);
}
export function encodeUrlSafe(str) {
return encode(str)
.replace(/+/g, '-')
.replace(///g, '_')
.replace(/=+$/, '');
}
export function decodeUrlSafe(str) {
const padded = str + '==='.slice((str.length + 3) % 4);
return decode(padded.replace(/-/g, '+').replace(/_/g, '/'));
}
export function encodeBytes(bytes) {
if (isNode) return Buffer.from(bytes).toString('base64');
const binString = Array.from(bytes, b => String.fromCodePoint(b)).join('');
return btoa(binString);
}
export function decodeToBytes(base64Str) {
if (isNode) return Buffer.from(base64Str, 'base64');
const binString = atob(base64Str);
return Uint8Array.from(binString, c => c.codePointAt(0));
}// Usage examples
import { encode, decode, encodeUrlSafe, decodeUrlSafe } from './base64.js';
encode('Hello 🌍'); // "SGVsbG8g8J+MjQ=="
decode('SGVsbG8g8J+MjQ=='); // "Hello 🌍"
encodeUrlSafe('[email protected]'); // "dXNlckBleGFtcGxlLmNvbQ" (no +, /, or =)
decodeUrlSafe('dXNlckBleGFtcGxlLmNvbQ'); // "[email protected]"Vanliga fallgropar att se upp med
- btoa() kastar undantag för icke-latinska tecken — valfritt tecken över kodpunkt 255 orsakar
InvalidCharacterError. Använd alltidTextEncoder-metoden ellerBuffer.from(str, 'utf8')i Node.js. - Utfyllnad spelar roll för avkodning — Base64-strängar måste ha en längd som är en multipel av 4. Saknad
=-utfyllnad gör attatob()tyst returnerar skräp eller kastar undantag beroende på webbläsare. Återställ alltid utfyllnad innan du avkodar URL-säkra strängar. - Buffer vs strängkodning i Node.js —
Buffer.from(str)är som standard UTF-8, menBuffer.from(str, 'binary')behandlar strängen som Latin-1-bytes. Fel kodning vid avkodning ger förvrängd utdata som kan vara svår att debugga. - Data-URI MIME-typ —
data:;base64,...(ingen MIME-typ) fungerar i vissa webbläsare men inte andra. Inkludera alltid MIME-typen:data:image/png;base64,.... - Radbrytningar i MIME Base64 — RFC 4648 tillåter implementationer att infoga radbrytningar var 76:e tecken (som e-postkodare gör).
atob()ochBuffer.from()hanterar båda detta, men om du genererar Base64 själv, lägg inte till radbrytningar om inte målsystemet förväntar sig dem.
Sammanfattning
Base64 i JavaScript är ett av de ämnen som ser triviala ut tills det biter dig.
Kortversionen: använd aldrig nakna btoa() för något användargenererat — omge det
med TextEncoder för att hantera Unicode korrekt. I Node.js är Buffer.from(str,
'utf8').toString('base64') rätt idiom. När den kodade strängen hamnar i en
URL eller JWT, byt till URL-säker variant. För snabba experiment eller engångskonverteringar sparar verktygen
Base64 Encoder, Base64 Decoder,
och JSON to Base64 tid. Sidan
MDN Base64-ordlistan
har också en solid webbläsarfokuserad referens om du behöver en andra åsikt.