base64.a85encode / b85encode / z85encode

Three 85-character alphabets for the same idea: a 32-bit word becomes 5 base-85 digits, so the output is only 25% larger than the input. They are not interchangeable — decode with the function that encoded.

base64 functionPython 3.4+ (z85: 3.13+)Live demo
Common call
base64.b85encode(data) · base64.a85decode(text, adobe=True)
Returns
bytes — b'Xk~0{Zy<MXa%^M' for b'hello world'
Replaces
Base64 when every byte of overhead counts
Watch out
Errors are plain ValueError here, not binascii.Error
base64.a85encode(bb — Data to encode, or text to decode.type: bytes-like (encode) · bytes-like | ASCII str (decode) · required, *, foldspacesfoldspaces — Ascii85 only: write 4 spaces as "y" (a btoa extension, not Adobe).type: bool · default: False=False, wrapcolwrapcol — a85encode only: insert a newline every wrapcol characters; 0 means one line.type: int · default: 0=0, padpad — a85encode / b85encode: pad the input with zero bytes to a multiple of 4 first (so the decoded result keeps the zeros).type: bool · default: False=False, adobeadobe — Ascii85 only: frame the output with <~ and ~> (encode) or expect that framing (decode).type: bool · default: False=False)
→ bytes

Demo

Live evaluation
The same bytes in Ascii85, Base85 and Z85.
Try:
Inputs
textstrany text
Code
import base64
data = 'hello world'.encode()
[base64.a85encode(data), base64.b85encode(data), base64.z85encode(data)]
Result
[b'BOu!rD]j7BEbo7', b'Xk~0{Zy<MXa%^M', b'xK#0@zY<mxA+]m']

All three use 5 characters per 4 bytes; a short last group is written with fewer characters (2 bytes → 3), so "hello world" (11 bytes) becomes 14 characters. Ascii85 shortens an all-zero group to z (and four spaces to y with foldspaces=True). The alphabets overlap, so the wrong decoder may succeed with garbage instead of failing — "HelloWorld" is the Z85 spec test vector, but all three accept it.

Parameters

NameTypeRequiredDescription
bbytes-like (encode) · bytes-like | ASCII str (decode)yesData to encode, or text to decode.
foldspacesboolno (False)Ascii85 only: write 4 spaces as "y" (a btoa extension, not Adobe).
wrapcolintno (0)a85encode only: insert a newline every wrapcol characters; 0 means one line.
padboolno (False)a85encode / b85encode: pad the input with zero bytes to a multiple of 4 first (so the decoded result keeps the zeros).
adobeboolno (False)Ascii85 only: frame the output with <~ and ~> (encode) or expect that framing (decode).
ignorecharsbytesno (b' \t\n\r\x0b')a85decode only: characters to skip — ASCII whitespace by default.

Return value

bytes — Encode: ASCII bytes, 5 characters per 4 input bytes (fewer for a short last group unless pad=True). Decode: the original bytes.

Common patterns

Git-style binary patch data
b85encode uses the alphabet of git binary diffs and Mercurial.
import base64
encoded = base64.b85encode(blob)
Adobe Ascii85 (PDF / PostScript streams)
adobe=True adds and expects the <~ ~> markers.
import base64
stream = base64.a85encode(data, adobe=True, wrapcol=75)
original = base64.a85decode(stream, adobe=True)
ZeroMQ CURVE keys (Python 3.13+)
Z85 is the text form of 32-byte ZeroMQ keys (40 characters).
import base64
key_text = base64.z85encode(public_key)  # 32 bytes → 40 characters

Examples

1. Ascii85
import base64 base64.a85encode(b'hello world')
Returns
b'BOu!rD]j7BEbo7'
2. Adobe framing
import base64 base64.a85encode(b'hello world', adobe=True)
Returns
b'<~BOu!rD]j7BEbo7~>'
3. Zeros fold to z
import base64 base64.a85encode(bytes(8))
Returns
b'zz'
4. Base85
import base64 base64.b85encode(b'hello world')
Returns
b'Xk~0{Zy<MXa%^M'
5. Z85 spec test vector
import base64 base64.z85encode(bytes([0x86, 0x4F, 0xD2, 0x6F, 0xB5, 0x59, 0xF7, 0x5B]))
Returns
b'HelloWorld'
6. Round trip
import base64 base64.z85decode(base64.z85encode(b'hello world'))
Returns
b'hello world'
7. pad=True keeps the zeros
import base64 base64.b85decode(base64.b85encode(b'hi', pad=True))
Returns
b'hi\x00\x00'
8. Bad character
import base64 base64.b85decode('Xk~0{Zy<MXa%^"')
Returns
ValueError: bad base85 character at position 13

Pitfalls

1. Adobe framing without adobe=True
The <~ and ~> markers are not Ascii85 digits; the default decoder chokes on them.
default
import base64
base64.a85decode('<~BOu!rD]j7BEbo7~>')
ValueError: Non-Ascii85 digit found: ~
adobe=True
import base64
base64.a85decode('<~BOu!rD]j7BEbo7~>', adobe=True)
b'hello world'
2. Catching binascii.Error
Unlike the Base64/32/16 decoders, the 85 family raises plain ValueError — catch ValueError to cover both.
except binascii.Error
import base64, binascii
try:
    base64.b85decode('ab,c')
except binascii.Error:
    print('bad input')
ValueError: bad base85 character at position 2
except ValueError
import base64
try:
    base64.b85decode('ab,c')
except ValueError:
    print('bad input')
bad input
3. Decoding with the wrong alphabet
Base85 and Z85 text often decode without error in the other decoder — to different bytes.
b85decode(z85 text)
import base64
base64.b85decode(base64.z85encode(b'hi'))
b'\xb8]'
z85decode
import base64
base64.z85decode(base64.z85encode(b'hi'))
b'hi'

When to use

Use it
  • PDF / PostScript streams (Ascii85, adobe=True)
  • Git binary patches, Mercurial (Base85)
  • ZeroMQ keys and messages (Z85, Python 3.13+)
Reach for something else
  • JSON, URLs, HTML or shell strings — all three alphabets contain < > &, and Ascii85 also quotes and backslash → Base64
  • Interoperating with anything that just says "Base64" → b64encode

Notes

CPython impl
Pure Python in Lib/base64.py: one shared _85encode helper with a different alphabet per codec; z85 translates to and from the base85 alphabet
Versions
a85* and b85* since Python 3.4; z85encode / z85decode since 3.13
Exceptions
ValueError: "Non-Ascii85 digit found: …", "Ascii85 overflow", "z inside Ascii85 5-tuple", "bad base85 character at position N", "base85 overflow in hunk starting at byte N" (z85 instead of base85 for Z85)

FAQ

Same arithmetic, different 85-character alphabets. Ascii85 uses ! to u (and z/y shortcuts); Base85 is the Git/Mercurial alphabet; Z85 is ZeroMQ's, chosen to be safe in source code strings. Their output is not interchangeable.