base64.b64decode

Accepts str or bytes, returns bytes. By default it quietly skips characters that are not Base64 — but it never forgives missing = padding.

base64 functionPython 2.4+Live demo
Common call
base64.b64decode(token).decode('utf-8')
Returns
bytes such as b'hello'
Replaces
Hand-written Base64 parsing; codecs.decode(data, "base64")
Watch out
Stripped = padding raises binascii.Error: Incorrect padding
base64.b64decode(ss — The Base64 data. A str must be pure ASCII, otherwise ValueError.type: bytes-like | str · required, altcharsaltchars — The 2 characters used instead of + and /, e.g. "-_". They are translated back to + and / before decoding.type: bytes | str · default: None=None, validatevalidate — False: characters outside the alphabet (spaces, newlines, junk) are discarded. True: any of them — and misplaced padding — raises binascii.Error.type: bool · default: False=False)
→ bytes

Demo

Live evaluation
Decode Base64 text and turn the bytes back into a str with UTF-8.
Try:
Inputs
datastrBase64 text
Code
import base64
base64.b64decode('aGVsbG8gd29ybGQ=').decode()
Result
'hello world'

Lenient mode drops every character outside A–Z a–z 0–9 + / before looking at the padding, so spaces and "!" vanish — and so do - and _, which is why URL-safe text decodes to b'' here. It also stops at the first complete padding, ignoring "aGk=" after it. validate=True turns each of those into an error. A length of 4k + 1 data characters can never be valid, so no amount of padding fixes "YWJjZ".

Parameters

NameTypeRequiredDescription
sbytes-like | stryesThe Base64 data. A str must be pure ASCII, otherwise ValueError.
altcharsbytes | strno (None)The 2 characters used instead of + and /, e.g. "-_". They are translated back to + and / before decoding.
validateboolno (False)False: characters outside the alphabet (spaces, newlines, junk) are discarded. True: any of them — and misplaced padding — raises binascii.Error.

Return value

bytes — The decoded data. Call .decode() on it when the original was text.

Common patterns

Decode Base64 to a string
Decode the Base64, then decode the bytes with the text encoding the sender used.
import base64
text = base64.b64decode(encoded).decode('utf-8')
Tolerate missing padding
-len(s) % 4 is exactly the number of = signs that were stripped.
import base64
def b64decode_nopad(s):
    return base64.b64decode(s + '=' * (-len(s) % 4))
Reject anything that is not clean Base64
validate=True plus except ValueError (binascii.Error is a subclass) covers every bad input.
import base64
try:
    data = base64.b64decode(user_input, validate=True)
except ValueError:
    data = None
Save decoded data to a file
Write the bytes in binary mode.
import base64
with open('photo.jpg', 'wb') as f:
    f.write(base64.b64decode(encoded))

Examples

1. str in, bytes out
import base64 base64.b64decode('aGVsbG8=')
Returns
b'hello'
2. Back to text
import base64 base64.b64decode('aGVsbG8=').decode()
Returns
'hello'
3. Newlines are skipped
import base64 base64.b64decode('aGVs\nbG8=')
Returns
b'hello'
4. Missing padding
import base64 base64.b64decode('aGVsbG8')
Returns
binascii.Error: Incorrect padding
5. Impossible length
import base64 base64.b64decode('a')
Returns
binascii.Error: Invalid base64-encoded string: number of data characters (1) cannot be 1 more than a multiple of 4
6. Strict mode
import base64 base64.b64decode('aGk=\n', validate=True)
Returns
binascii.Error: Excess data after padding
7. URL-safe input via altchars
import base64 base64.b64decode('-_8=', altchars='-_')
Returns
b'\xfb\xff'
8. Non-ASCII str
import base64 base64.b64decode('aGVsbG8=é')
Returns
ValueError: string argument should contain only ASCII characters

Pitfalls

1. Stripped padding (JWTs, URLs, copied tokens)
Many producers drop the trailing = signs. b64decode requires them — add them back.
as received
import base64
base64.b64decode('eyJzdWIiOiIxMjMifQ')
binascii.Error: Incorrect padding
pad it
import base64
s = 'eyJzdWIiOiIxMjMifQ'
base64.b64decode(s + '=' * (-len(s) % 4))
b'{"sub":"123"}'
2. Silently dropping characters
The default mode discards anything outside the alphabet, so URL-safe or corrupted input "succeeds" with the wrong bytes. validate=True makes it fail loudly.
default
import base64
base64.b64decode('-_-_')
b''
validate=True
import base64
base64.b64decode('-_-_', validate=True)
binascii.Error: Only base64 data is allowed
3. Decoding binary data as text
b64decode returns whatever bytes were encoded. If they are an image or a key, .decode() fails — keep them as bytes.
.decode()
import base64
base64.b64decode('iVBORw0KGgo=').decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
keep bytes
import base64
base64.b64decode('iVBORw0KGgo=')[1:4]
b'PNG'

When to use

Use it
  • Base64 from JSON, HTTP headers, data: URIs, config files, email
  • Standard alphabet (+ and /) input; altchars= for others
Reach for something else
  • URL-safe input (- and _) → urlsafe_b64decode, or validate=True to catch it
  • Untrusted input you must reject when malformed → pass validate=True
  • Multi-line MIME bodies → decodebytes works too; b64decode already skips the newlines

Notes

CPython impl
binascii.a2b_base64(s, strict_mode=validate) in C (the strict_mode parameter exists since Python 3.11)
Padding
Decoding stops at the first complete padding, so anything after "==" is ignored in lenient mode
Exceptions
binascii.Error (a ValueError) for bad data; ValueError for non-ASCII str; TypeError for other types

FAQ

base64.b64decode(s).decode('utf-8'). b64decode accepts the str directly and returns bytes; .decode turns the bytes into text.