Die Formel
Für eine Eingabe von n Bytes hat Base64 mit Padding (der Standard in RFC 4648) genau diese Länge:
length = 4 × ceil(n / 3)
Ohne Padding, wie bei Base64URL für JWTs, gilt:
length = ceil(4n / 3)
Die beiden unterscheiden sich um die Anzahl der =-Zeichen, also 0, 1 oder 2 je nach n mod 3. Woher sie kommen, erklärt die Anleitung zum Padding.
Umgekehrt ergibt ein Base64-String mit Padding und der Länge L dekodiert:
bytes = 3 × L / 4 − (number of trailing "=")
TWFu sind also 3 Bytes, TWE= sind 2 und TQ== ist 1. Entfernen Sie vor dem Zählen Leerraum und Zeilenumbrüche. Der Base64-Größenrechner rechnet in beide Richtungen, einschließlich Zeilenumbrüchen und Data-URI-Präfixen.
Im Code:
import base64, math, os
for n in [1, 2, 3, 100, 1000]:
data = os.urandom(n)
assert len(base64.b64encode(data)) == 4 * math.ceil(n / 3)
const b64Len = (n) => 4 * Math.ceil(n / 3);
const rawLen = (s) => (s.length * 3) / 4 - (s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0);
b64Len(1000); // 1336
rawLen("TWE="); // 2
Warum der Zuwachs 33 % beträgt
Ein Byte hat 8 Bit. Ein Base64-Zeichen trägt 6 Bit Daten, weil es eines von 64 = 2⁶ Symbolen ist, wird aber als 8-Bit-ASCII-Byte gespeichert. Jedes Ausgabebyte enthält also 6 nützliche Bits, und die Ausgabe muss 8/6 = 4/3 der Eingabe betragen. Das sind 33,3 % mehr, und das ist eine harte Untergrenze: Keine Base64-Implementierung kann es besser, ohne das Alphabet aufzugeben. (Wie die Bits neu gruppiert werden, zeigt So funktioniert Base64 Schritt für Schritt.)
Bei kleinen Eingaben verschlechtert das Padding das Verhältnis, da die Ausgabe immer in Blöcken zu 4 kommt. Aus einem Byte werden 4 Zeichen, ein Zuwachs von 300 %. Ab einigen hundert Bytes fällt das Padding nicht mehr ins Gewicht, und das Verhältnis pendelt sich bei 4/3 ein.
Es gibt dichtere Textkodierungen. Base85 speichert 4 Bytes in 5 Zeichen (25 % Zuwachs), und Base91 kommt etwas tiefer. Sie werden weniger breit unterstützt, und ihre Alphabete enthalten Zeichen, die in manchen Kontexten Ärger machen. Den Vergleich finden Sie unter Base64 vs. Hex, Base32, Base58, Base85.
Zeilenumbrüche: MIME, PEM und Kommandozeilen-Tools
Manche Formate brechen Base64 in Zeilen um, und die Zeilenenden zählen zur Größe.
| Format | Zeilenlänge | Zeilenende | Gesamtzuwachs |
|---|---|---|---|
| Reines Base64 (RFC 4648) | kein Umbruch | keines | 33,3 % |
| MIME-E-Mail (RFC 2045) | 76 | CRLF (2 Bytes) | 36,8 % |
GNU base64, Python encodebytes | 76 | LF (1 Byte) | 35,1 % |
| PEM-Zertifikate und -Schlüssel | 64 | LF | 35,4 % |
Der MIME-Wert ergibt sich aus 4/3 × 78/76: Je 76 Zeichen Base64 kommen 2 Bytes CRLF hinzu. Mit L = 4 × ceil(n / 3) beträgt die Größe einschließlich eines CRLF nach jeder Zeile, auch der letzten:
mime_length = L + 2 × ceil(L / 76)
Jede volle Zeile mit 76 Zeichen enthält genau 57 Eingabebytes, weshalb MIME-Encoder Daten in Blöcken zu 57 Bytes verarbeiten. Mehr zu E-Mail unter Base64 in E-Mails, und der MIME-Base64-Encoder erzeugt umbrochene Ausgabe.
Größentabelle
Berechnet mit den Formeln oben und gegen das Python-Modul base64 geprüft.
| Eingabe | Base64 mit Padding | Ohne Padding | MIME (76 + CRLF) | Zuwachs (mit Padding) |
|---|---|---|---|---|
| 1 Byte | 4 | 2 | 6 | 300 % |
| 2 Bytes | 4 | 3 | 6 | 100 % |
| 3 Bytes | 4 | 4 | 6 | 33,3 % |
| 10 Bytes | 16 | 14 | 18 | 60 % |
| 57 Bytes | 76 | 76 | 78 | 33,3 % |
| 100 Bytes | 136 | 134 | 140 | 36 % |
| 1.000 Bytes | 1.336 | 1.334 | 1.372 | 33,6 % |
| 1 KiB (1.024) | 1.368 | 1.366 | 1.404 | 33,6 % |
| 1 MB (10⁶) | 1.333.336 | 1.333.334 | 1.368.424 | 33,3 % |
| 1 MiB (1.048.576) | 1.398.104 | 1.398.102 | 1.434.898 | 33,3 % |
| 10 MiB | 13.981.016 | 13.981.014 | 14.348.938 | 33,3 % |
| 25 MB (25 × 10⁶) | 33.333.336 | 33.333.334 | 34.210.530 | 33,3 % |
Die letzte Zeile betrifft E-Mail. SMTP-Größenlimits (die Erweiterung SIZE, RFC 1870) zählen die Nachricht so, wie sie übertragen wird, einschließlich Kodierung. Eine 25-MB-Datei wird bei der Übertragung also zu etwa 34,2 MB und kommt nicht durch ein Serverlimit von 25 MB. Manche Anbieter beziehen ihre Limits stattdessen auf den Anhang, prüfen Sie also, wie Ihrer zählt.
Was Kompression bewirkt
Kompression wirkt auf zwei Arten mit Base64 zusammen, und die Reihenfolge zählt.
Komprimieren Sie vor dem Kodieren, wann immer Sie beide Enden kontrollieren. Base64 komprimierter Daten ist 4/3 einer kleineren Zahl. Für den Text der GPL-3-Lizenz (35.149 Bytes) haben wir mit zlib von Node.js bei gzip-Stufe 9 gemessen:
| Pipeline | Größe |
|---|---|
| Rohtext | 35.149 |
| Nur Base64 | 46.868 |
| Base64, dann gzip | 17.465 |
| gzip, dann Base64 | 16.124 |
| Nur gzip | 12.091 |
Das Tool Gzip + Base64 führt die Pipeline „gzip, dann Base64“ im Browser aus.
Kompression beim Transport holt bei Binärdaten den Großteil des Zuwachses zurück. Reist ein Base64-String in einer mit gzip oder Brotli komprimierten HTTP-Antwort, drückt der Kompressor die 6-Bit-Zeichen wieder in Richtung 6 Bit je Zeichen. 1 MiB Zufallsbytes wuchs in Base64 auf 1.398.104 Zeichen; mit gzip waren es 1.053.023 Bytes (0,4 % über den Rohdaten), und Brotli kam auf 1.048.805. Dieselben Daten mit MIME-Zeilenumbrüchen ergaben mit gzip 1.088.689, die CRLFs kosteten also selbst nach der Kompression etwa 3,4 %.
Bei Text ist es anders. Base64 zerstört die Wiederholungen, auf die Kompressoren angewiesen sind, daher komprimiert sich Base64-Text viel schlechter als der Text selbst: 17.465 gegenüber 12.091 Bytes in der Tabelle oben. Der Artikel Performance von Data-URIs enthält Messungen für PNG, JPEG, WOFF2 und SVG.
Limits für URLs, Header und Cookies
Base64 bläht alles auf, was Sie in eine URL, einen Header oder ein Cookie setzen, und alle drei haben Limits.
- URLs. RFC 9110 empfiehlt, dass Sender und Empfänger URIs mit mindestens 8.000 Oktetten unterstützen. Viele Server hören standardmäßig in dieser Gegend auf: nginx reserviert für die Anfragezeile Header-Puffer von 8 KB, und
LimitRequestLinevon Apache steht standardmäßig auf 8.190 Bytes. Längere URLs scheitern meist mit414 URI Too Long. Mit Base64URL ist das Platz für rund 6.000 Bytes Daten, abzüglich des Rests der URL. - Header. Dieselben Serverpuffer gelten für jede Headerzeile, was bei langen JWTs in
Authorization: Bearer ...und großen Basic-Auth-Zugangsdaten eine Rolle spielt. - Cookies. RFC 6265 verlangt von Browsern, mindestens 4.096 Bytes pro Cookie zu unterstützen, einschließlich Name und Attributen. Das sind nach der Base64-Kodierung etwa 3 KB Daten.
Nähert sich eine Base64-Payload einem dieser Limits, senden Sie sie stattdessen im Request-Body, oder speichern Sie sie auf dem Server und übergeben eine ID.
Geben Sie eine Byteanzahl ein oder fügen Sie einen String ein, um kodierte und dekodierte Größen zu sehen, mit oder ohne Zeilenumbrüche.
Häufige Fragen
Wie viel größer ist Base64 als die Originaldatei?
Etwa 33,3 % bei allem, was größer als ein paar Bytes ist. Mit MIME-Zeilenumbrüchen (76 Zeichen plus CRLF) sind es etwa 36,8 %.
Wie berechne ich die Originalgröße aus einem Base64-String?
Nehmen Sie die Länge ohne Leerraum, multiplizieren Sie mit 3/4 und ziehen Sie die Anzahl der = am Ende ab. Zum Beispiel ist TWE= 4 × 3/4 − 1 = 2 Bytes groß.
Warum ergibt eine Eingabe von 1 Byte 4 Zeichen?
Mit Padding gibt Base64 immer vollständige 4-Zeichen-Blöcke aus. Ein Byte füllt 2 Zeichen, die anderen 2 sind =, winzige Eingaben haben daher einen viel höheren relativen Zuwachs.
Kann ich Base64 kleiner machen?
Komprimieren Sie die Daten vor dem Kodieren, zum Beispiel mit gzip, und lassen Sie das Padding weg, wenn der Empfänger das erlaubt. Base64 selbst hat ein festes Verhältnis; dichtere Textkodierungen wie Base85 gibt es, sie werden aber weniger breit unterstützt.