Datei hochladen
  1. base64hub
  2. Base64 im Code
  3. Python
Code

Base64 in Python

Das Modul base64 der Standardbibliothek deckt alles ab: Standard- und URL-sicheres Alphabet, Dateien und MIME-Zeilen. Jedes Snippet unten wurde mit Python 3.13 ausgeführt.

Einen String kodieren und dekodieren

Die Base64-Funktionen von Python arbeiten mit Bytes, Text muss also zuerst in UTF-8 kodiert und am Ende wieder dekodiert werden. Einen der beiden Schritte zu vergessen ist der häufigste Fehler.

import base64

s = "héllo wörld"
encoded = base64.b64encode(s.encode("utf-8")).decode("ascii")
print(encoded)                                    # aMOpbGxvIHfDtnJsZA==

decoded = base64.b64decode(encoded).decode("utf-8")
print(decoded)                                    # héllo wörld

b64decode akzeptiert sowohl str als auch bytes, b64encode nimmt dagegen nur Bytes-ähnliche Objekte. Ein String löst TypeError: a bytes-like object is required, not 'str' aus.

Um ein Ergebnis von Hand zu prüfen, fügen Sie es in den Base64-Decoder ein, der lokal im Browser läuft.

URL-sicheres Base64 mit und ohne Padding

Das URL-sichere Alphabet ersetzt + durch - und / durch _ (siehe Base64 vs. Base64URL). Python behält das =-Padding; entfernen Sie es selbst, wenn das Zielformat (JWT, viele APIs) keines will.

data = b"<<???>>"
print(base64.b64encode(data))                     # b'PDw/Pz8+Pg=='
print(base64.urlsafe_b64encode(data))             # b'PDw_Pz8-Pg=='
print(base64.urlsafe_b64encode(data).rstrip(b"="))  # b'PDw_Pz8-Pg'

Zum Dekodieren von Eingaben ohne Padding muss das Padding wieder ergänzt werden, weil Python auf einer durch 4 teilbaren Länge besteht:

def b64url_decode(s: str) -> bytes:
    return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))

print(b64url_decode("PDw_Pz8-Pg"))                # b'<<???>>'

b64encode und b64decode nehmen außerdem ein Argument altchars entgegen, einen 2-Byte-String, der +/ ersetzt. altchars=b"-_" entspricht den URL-sicheren Funktionen.

print(base64.b64decode("PDw_Pz8-Pg==", altchars="-_"))  # b'<<???>>'

Eine Datei kodieren und dekodieren

Bei Dateien, die in den Speicher passen, lesen Sie die Bytes und kodieren sie in einem Aufruf:

from pathlib import Path

b64 = base64.b64encode(Path("hello.txt").read_bytes()).decode("ascii")
print(b64)                                        # aGVsbG8K
Path("hello-copy.txt").write_bytes(base64.b64decode(b64))

Für eine einmalige Umwandlung ohne Code erledigt das Tool Datei in Base64 dasselbe im Browser.

Große Dateien und Streaming

Base64 bildet je 3 Eingabebytes auf 4 Ausgabezeichen ab. Sie können einen Stream also in Blöcken kodieren, solange jeder Block außer dem letzten ein Vielfaches von 3 Bytes ist. Dann erscheint kein Padding in der Mitte, und die aneinandergehängte Ausgabe entspricht einer Kodierung in einem einzigen Aufruf.

CHUNK = 3 * 1024 * 256  # 768 KiB, a multiple of 3

with open("big.bin", "rb") as src, open("big.b64", "wb") as dst:
    while chunk := src.read(CHUNK):
        dst.write(base64.b64encode(chunk))

Wir haben das an einer zufälligen 100-KB-Datei mit base64 -w 0 verglichen: Byte für Byte identisch. Das Dekodieren in Blöcken funktioniert genauso mit Blockgrößen, die ein Vielfaches von 4 Zeichen sind, sofern die Eingabe keine Zeilenumbrüche enthält.

MIME-Zeilenumbruch

E-Mail und manche Altsysteme wollen Zeilen mit höchstens 76 Zeichen (RFC 2045). Das erledigt encodebytes, und base64.encode / base64.decode tun es zwischen Dateiobjekten:

print(base64.encodebytes(b"x" * 60))
# b'eHh4eHh4...eHh4\neHh4\n'   (76 chars, newline, rest, newline)

with open("big.bin", "rb") as src, open("big.mime", "wb") as dst:
    base64.encode(src, dst)
with open("big.mime", "rb") as src, open("big.out", "wb") as dst:
    base64.decode(src, dst)

Beachten Sie den abschließenden Zeilenumbruch: encodebytes fügt immer einen an. Eine Online-Variante ist der MIME-Base64-Encoder.

Eingaben prüfen

Standardmäßig ist b64decode tolerant: Es wirft vor dem Dekodieren jedes Zeichen außerhalb des Alphabets weg. Das verdeckt Bugs. Übergeben Sie validate=True, um es streng zu machen.

import binascii

print(base64.b64decode("aGk=!!"))                 # b'hi'  (junk ignored)

try:
    base64.b64decode("aGk=!!", validate=True)
except binascii.Error as e:
    print(e)                                      # Only base64 data is allowed

Mit validate=True gelten auch Zeilenumbrüche als ungültig; entfernen Sie MIME-Zeilenumbrüche also vorher. Die Fehler, die Ihnen begegnen, alle vom Typ binascii.Error (einer Unterklasse von ValueError):

EingabeMeldung
aGkIncorrect padding
aInvalid base64-encoded string: number of data characters (1) cannot be 1 more than a multiple of 4
aGk== mit validate=TrueExcess padding not allowed
aGk=!! mit validate=TrueOnly base64 data is allowed

Die Anleitung zu Base64-Fehlern erklärt, was jeden dieser Fehler verursacht, und der Base64-Validator zeigt, wo ein String bricht.

Häufige Fallstricke

URL-sichere Eingabe in b64decode. Ohne validate=True werden die Zeichen - und _ stillschweigend verworfen, und Sie erhalten Datenmüll statt eines Fehlers:

print(base64.b64decode("PDw_Pz8-Pg=="))           # b'<<\x0f\xcf\xc3\xe0'
print(base64.urlsafe_b64decode("PDw_Pz8-Pg=="))   # b'<<???>>'

urlsafe_b64decode akzeptiert auch Standardeingaben und ist daher die sicherere Wahl, wenn Sie nicht wissen, welches Alphabet Sie bekommen haben.

Binärdaten als Text dekodieren. Ist die Payload ein Bild oder ein ZIP, scheitert .decode("utf-8") mit UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte. Behalten Sie die Bytes und schreiben Sie sie in eine Datei.

Das b'...' in der Ausgabe. Gibt man den Rückgabewert von b64encode aus, erscheint ein Bytes-Literal. Landet dieses b' in JSON oder einem Header, haben Sie .decode("ascii") vergessen.

Base64 für einen Schutz halten. Es ist eine Kodierung, und jeder kann sie umkehren. Siehe Kodierung vs. Verschlüsselung.

Versionshinweise

  • base64.b64encode, b64decode, urlsafe_* und altchars gibt es in jeder Version von Python 3.
  • b64decode akzeptiert seit Python 3.3 ASCII-str als Eingabe (nicht nur Bytes).
  • encodestring und decodestring wurden in 3.9 entfernt; verwenden Sie encodebytes und decodebytes.
  • binascii.b2a_base64(data, newline=False) (3.6+) ist die Low-Level-Funktion hinter b64encode und liefert für b"hi" den Wert b'aGk='.
  • Dasselbe Modul hat außerdem b32encode, b16encode, b85encode und a85encode für andere Alphabete.

Häufige Fragen

Warum liefert b64encode b'...' statt eines Strings?

Die Base64-Funktionen in Python nehmen Bytes entgegen und liefern Bytes zurück. Rufen Sie .decode("ascii") auf dem Ergebnis auf, um einen str zu erhalten, und .encode("utf-8") auf Text, bevor Sie ihn kodieren.

Wie dekodiere ich in Python Base64 ohne Padding?

Ergänzen Sie die fehlenden = vor dem Dekodieren: s + "=" * (-len(s) % 4). Python lehnt Eingaben ohne Padding mit binascii.Error: Incorrect padding ab.

Was ist der Unterschied zwischen b64decode und urlsafe_b64decode?

urlsafe_b64decode übersetzt - und _ vor dem Dekodieren in + und /. Das einfache b64decode verwirft - und _ stillschweigend als Datenmüll, Sie erhalten also falsche Bytes statt eines Fehlers, sofern Sie nicht validate=True übergeben.

Gibt es base64.encodestring noch?

Nein. encodestring und decodestring wurden in Python 3.9 entfernt. Verwenden Sie encodebytes und decodebytes für Ausgabe im MIME-Stil mit Zeilenumbrüchen.

Weiterlesen