base64.encodebytes / decodebytes

The "legacy interface" for email and PEM-style data: encodebytes breaks the output every 57 input bytes (76 characters) and ends with a newline. Both functions accept only bytes — not str.

base64 functionPython 3.1+Live demo
Common call
base64.encodebytes(data)
Returns
bytes such as b'aGk=\n'
Replaces
encodestring / decodestring (removed in Python 3.9)
Watch out
Adds a trailing newline even for short input; rejects str
base64.encodebytes(ss — Data to encode, or Base64 bytes to decode. A str raises TypeError in both directions.type: bytes-like · required)
→ bytes

Demo

Live evaluation
Encode text repeated n times and look at the lines encodebytes produces.
Try:
Inputs
textstrany text
nintrepeat count
Code
import base64
base64.encodebytes('hi'.encode() * 1).splitlines()
Result
[b'aGk=']

57 input bytes are exactly one 76-character line; at 60 bytes a second, short line starts. The output always ends with a newline, which is why even "hi" gives one line, while empty input gives no line at all. decodebytes is the lenient decoder: like b64decode without validate, it drops characters such as * but still requires padding.

Parameters

NameTypeRequiredDescription
sbytes-likeyesData to encode, or Base64 bytes to decode. A str raises TypeError in both directions.

Return value

bytes — Encode: Base64 in lines of 76 characters plus b"\n", with a trailing newline. Decode: the original bytes.

Common patterns

PEM block from DER bytes
PEM uses 64-character lines, so build it with textwrap rather than encodebytes (76).
import base64, textwrap
body = '\n'.join(textwrap.wrap(base64.b64encode(der).decode('ascii'), 64))
pem = f'-----BEGIN CERTIFICATE-----\n{body}\n-----END CERTIFICATE-----\n'
MIME attachment body
encodebytes gives RFC 2045 line lengths.
import base64
with open('report.pdf', 'rb') as f:
    body = base64.encodebytes(f.read()).decode('ascii')

Examples

1. Trailing newline
import base64 base64.encodebytes(b'hi')
Returns
b'aGk=\n'
2. 76 characters per line
import base64 [len(line) for line in base64.encodebytes(bytes(120)).splitlines()]
Returns
[76, 76, 8]
3. Decode multi-line input
import base64 base64.decodebytes(b'eHh4\neHh4\n')
Returns
b'xxxxxx'
4. str is rejected
import base64 base64.decodebytes('aGk=')
Returns
TypeError: expected bytes-like object, not str
5. Same bytes as b64decode
import base64 base64.decodebytes(b'aGVsbG8=') == base64.b64decode('aGVsbG8=')
Returns
True

Pitfalls

1. Newlines in a token
encodebytes is for line-oriented formats. In headers, JSON or URLs, the newlines break things — use b64encode.
encodebytes
import base64
base64.encodebytes(b'user:pass').decode()
'dXNlcjpwYXNz\n'
b64encode
import base64
base64.b64encode(b'user:pass').decode()
'dXNlcjpwYXNz'
2. Passing a str to decodebytes
Unlike b64decode, decodebytes does not accept ASCII str.
str
import base64
base64.decodebytes('aGk=')
TypeError: expected bytes-like object, not str
bytes
import base64
base64.decodebytes('aGk='.encode())
b'hi'

When to use

Use it
  • Email (MIME) bodies and other formats limited to 76-character lines
  • Decoding line-wrapped Base64 you already have as bytes
Reach for something else
  • Tokens, headers, JSON, URLs → b64encode (no newlines)
  • PEM (64-character lines) → b64encode plus textwrap
  • Strict validation → b64decode(s, validate=True)

Notes

CPython impl
MAXBINSIZE = 57 bytes per line; each chunk goes through binascii.b2a_base64, which appends b"\n". decodebytes is binascii.a2b_base64(s) after a bytes-like type check
History
encodestring / decodestring were the old names; deprecated since 3.1 and removed in 3.9

FAQ

You used encodebytes (or encode), which produces MIME lines of 76 characters with a newline after each — including the last. Use b64encode for a single line without newlines.