Datei hochladen
  1. base64hub
  2. Base64 verstehen
  3. Uint8Array.toBase64()
Anleitung

Uint8Array.toBase64 und fromBase64 in JavaScript

JavaScript hat endlich eine Base64-API, die mit Bytes arbeitet, Base64URL beherrscht und festlegen lässt, wie streng dekodiert wird. Sie ersetzt die meisten Einsätze von btoa, atob und selbst geschriebenen Schleifen.

Kodieren und Dekodieren in einer Zeile

Die API bringt drei Methoden für Base64 und drei für Hex mit:

MethodeWas sie tut
bytes.toBase64(options)Uint8Array in eine Base64-Zeichenkette
Uint8Array.fromBase64(string, options)Base64-Zeichenkette in ein neues Uint8Array
bytes.setFromBase64(string, options)In ein vorhandenes Uint8Array dekodieren
bytes.toHex()Uint8Array in eine Hex-Zeichenkette in Kleinbuchstaben
Uint8Array.fromHex(string)Hex-Zeichenkette in ein neues Uint8Array
bytes.setFromHex(string)Hex in ein vorhandenes Uint8Array dekodieren

Text muss zuerst zu Bytes werden. TextEncoder erzeugt immer UTF-8, Unicode funktioniert also ohne Tricks:

const bytes = new TextEncoder().encode("Grüße, 世界");
const b64 = bytes.toBase64();
console.log(b64); // "R3LDvMOfZSwg5LiW55WM"

const back = new TextDecoder().decode(Uint8Array.fromBase64(b64));
console.log(back); // "Grüße, 世界"

Ein ArrayBuffer, etwa aus fetch().arrayBuffer() oder crypto.subtle.digest(), braucht eine Sicht: new Uint8Array(buffer).toBase64(). Andere Typed Arrays haben die Methoden überhaupt nicht. Um den rohen Speicher eines Uint16Array zu kodieren, legen Sie eine Sicht darauf an: new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength).

Optionen: alphabet, omitPadding, lastChunkHandling

alphabet

"base64" (Standard) verwendet + und /. "base64url" verwendet - und _. Die Option gilt für Kodieren und Dekodieren, und ein Decoder, der auf ein Alphabet eingestellt ist, lehnt die Zeichen des anderen ab.

const data = new Uint8Array([251, 255]);
data.toBase64();                                         // "+/8="
data.toBase64({ alphabet: "base64url" });                // "-_8="
data.toBase64({ alphabet: "base64url", omitPadding: true }); // "-_8"

Uint8Array.fromBase64("-_8", { alphabet: "base64url" }); // Uint8Array [251, 255]
Uint8Array.fromBase64("-_8");                            // SyntaxError

omitPadding

toBase64 fügt standardmäßig =-Padding hinzu, auch beim Base64URL-Alphabet. Übergeben Sie omitPadding: true für eine Ausgabe im JWT-Stil. Beim Dekodieren steuert lastChunkHandling das Padding.

lastChunkHandling

Diese Option entscheidet, was fromBase64 und setFromBase64 mit der letzten Zeichengruppe machen. Die drei Modi, getestet mit Eingaben, die die Bytes von Hi?> ergeben:

Eingabe"loose" (Standard)"strict""stop-before-partial"
SGk/Pg==Hi?>Hi?>Hi?>
SGk/Pg (ohne Padding)Hi?>SyntaxErrorHi? (stoppt vor Pg)
SGk/Ph== (Füllbits ungleich null)Hi?>SyntaxErrorHi?>
SGk/P (ein übriges Zeichen)SyntaxErrorSyntaxErrorHi?
  • loose verhält sich wie atob: Padding ist optional, und übrige Bits im letzten Zeichen werden ignoriert.
  • strict akzeptiert nur kanonische Eingaben mit Padding, wie RFC 4648 sie beschreibt. Nutzen Sie es, wenn die kodierte Form eindeutig sein muss, etwa wenn Base64-Zeichenketten verglichen oder signiert werden.
  • stop-before-partial dekodiert alle vollständigen Gruppen aus 4 Zeichen und lässt ein unvollständiges Ende liegen. Das ist für Streaming gedacht, bei dem der Rest der Gruppe mit dem nächsten Stück kommt.

In jedem Modus wird ASCII-Leerraum (Leerzeichen, Tabs, Zeilenumbrüche) übersprungen, MIME-umbrochene Eingaben lassen sich also direkt dekodieren. Jedes andere Zeichen außerhalb des Alphabets wirft einen SyntaxError.

In einen vorhandenen Puffer schreiben

setFromBase64 und setFromHex dekodieren in ein Uint8Array, das Sie bereits haben, und geben zurück, wie viel sie verbraucht haben:

const target = new Uint8Array(8);
const result = target.setFromBase64("SGVsbG8gd29ybGQ=");
console.log(result); // { read: 8, written: 6 }

Hello world hat 11 Bytes, das Ziel fasst 8. Der Decoder schreibt nur vollständige 3-Byte-Gruppen, die hineinpassen, er hört also nach 6 Bytes auf und meldet, dass er 8 Zeichen gelesen hat. Rufen Sie ihn mit dem Rest der Zeichenkette und einem subarray des Ziels erneut auf, um fortzufahren. Zusammen mit stop-before-partial können Sie so einen Stream Stück für Stück in einen vorab angelegten Puffer dekodieren:

const out = new Uint8Array(1024);
const { read, written } = out.setFromBase64("SGk/Pg", {
  lastChunkHandling: "stop-before-partial",
});
// read: 4, written: 3. Keep "Pg" and prepend it to the next chunk.

Die Hex-Methoden folgen demselben Muster. toHex() schreibt immer Kleinbuchstaben, fromHex() akzeptiert beide Schreibweisen, und eine ungerade Anzahl Ziffern ist ein SyntaxError:

new Uint8Array([0xde, 0xad, 0xbe, 0xef]).toHex(); // "deadbeef"
Uint8Array.fromHex("CAFE");                       // Uint8Array [202, 254]

Warum btoa und atob umständlich sind

btoa und atob stammen aus den Anfangstagen der Browser und arbeiten mit „Binary Strings“: JavaScript-Zeichenketten, in denen jeder Zeichencode ein Bytewert von 0 bis 255 ist. Das verursacht drei Probleme.

Unicode wirft einen Fehler oder geht stillschweigend schief. Zeichen oberhalb von U+00FF lassen btoa einen InvalidCharacterError werfen (Chrome: „The string to be encoded contains characters outside of the Latin1 range“). Zeichen zwischen U+0080 und U+00FF sind schlimmer: Sie werden ohne Fehler kodiert, als Latin-1. btoa("Grüße") liefert R3L832U=, während die UTF-8-Kodierung, die jedes andere System erwartet, R3LDvMOfZQ== lautet.

Dekodieren liefert eine Zeichenkette, keine Bytes. atob("Q2Fmw6k=") liefert "Café". Um echten Text zu erhalten, wandeln Sie die Zeichenkette in Bytes um und dekodieren diese dann als UTF-8, was eine Schleife oder Uint8Array.from(atob(s), c => c.charCodeAt(0)) erfordert.

Große Eingaben brauchen Sorgfalt. Der verbreitete Einzeiler btoa(String.fromCharCode(...bytes)) übergibt jedes Byte als Funktionsargument, und bei einem Array mit 1 MB wirft er RangeError: Maximum call stack size exceeded. Man muss die Zeichenkette stückweise aufbauen.

Außerdem gibt es keine Unterstützung für Base64URL und keine Kontrolle über Padding oder Strenge. Der alte Workaround btoa(unescape(encodeURIComponent(text))) erzeugt zwar UTF-8-Base64, stützt sich aber auf das veraltete unescape. Mit der neuen API wird all das zu new TextEncoder().encode(text).toBase64().

Unterstützung in Browsern und Node.js

Die Methoden stammen aus dem TC39-Proposal „Uint8Array to/from Base64“, das im Juli 2025 Stage 4 erreichte und Teil von ECMAScript 2026 ist.

LaufzeitumgebungErste Version mit allen sechs Methoden
Chrome, Edge140
Firefox133
Safari (macOS und iOS)18.2
Node.js25.0.0

Mit Chrome 140 wurde die Funktion im September 2025 Baseline, jeder aktuelle große Browser hat sie also. In Node.js haben wir die Methoden direkt getestet. Node 25.0.0 und 26.12.1 haben alle sechs. Node 24.22.1, eine LTS-Version, hat standardmäßig keine davon. Seine V8-Version akzeptiert ein experimentelles Flag --js-base-64, in unserem Test machte dieses Flag aber toBase64, fromBase64, toHex und fromHex verfügbar, ohne setFromBase64 oder setFromHex, betrachten Sie Node 24 also als nicht unterstützt. Unter Node 24 und älter nutzen Sie Buffer.from(b64, "base64") und buf.toString("base64"), die auch "base64url" akzeptieren. Deno 2.5 und Bun 1.1.22 unterstützen die API laut den Kompatibilitätsdaten von MDN ebenfalls.

Ein Fallback für ältere Laufzeitumgebungen

Prüfen Sie die Verfügbarkeit und weichen Sie auf btoa/atob mit stückweiser Verarbeitung aus. Diese Version wurde unter Node 24 (Fallback-Pfad) und Node 26 (nativer Pfad) mit UTF-8-Text und einem Array mit 1 MB getestet:

function bytesToBase64(bytes) {
  if (typeof bytes.toBase64 === "function") return bytes.toBase64();
  let bin = "";
  for (let i = 0; i < bytes.length; i += 0x8000) {
    bin += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
  }
  return btoa(bin);
}

function base64ToBytes(b64) {
  if (typeof Uint8Array.fromBase64 === "function") return Uint8Array.fromBase64(b64);
  return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
}

Der Fallback deckt nur die Standardoptionen ab. Brauchen Sie base64url, strict oder setFromBase64 überall, nehmen Sie ein vollständiges Polyfill: core-js liefert eines als es.uint8-array.to-base64, es.uint8-array.from-base64 und verwandte Module.

Um Kodierungen ohne Code auszuprobieren, nutzen Sie den Base64-Encoder und den Decoder oder Base64URL für das URL-sichere Alphabet. Weitere JavaScript-Beispiele, auch zu Nodes Buffer, finden Sie unter Base64 in JavaScript und Base64 in Node.js.

Häufige Fragen

Kann ich die neue Base64-API heute schon ausliefern?

In Browsern ja: Sie ist in Chrome und Edge 140, Firefox 133 und Safari 18.2 enthalten. In Node.js braucht sie Version 25 oder neuer. Behalten Sie einen Fallback, wenn Sie ältere Browser oder Node 24 und älter unterstützen.

Akzeptiert Uint8Array.fromBase64 Base64URL?

Ja, mit { alphabet: "base64url" }. Ohne diese Option führen - und _ zu einem SyntaxError. Im standardmäßigen toleranten Modus ist das Padding bei beiden Alphabeten optional.

Wie kodiere ich eine Zeichenkette mit toBase64?

Wandeln Sie sie zuerst in UTF-8-Bytes um: new TextEncoder().encode(text).toBase64(). Zum Dekodieren kehren Sie das mit new TextDecoder().decode(Uint8Array.fromBase64(b64)) um.

Warum ist toBase64 auf meinem Buffer oder Uint16Array keine Funktion?

Die Methoden gibt es nur auf Uint8Array und seinen Unterklassen. Nodes Buffer bekommt sie ab Node 25. Bei anderen Typed Arrays legen Sie eine Sicht auf den Speicher an: new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength).

Weiterlesen