.. SETUP VARIABLES
.. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg
:target: https://github.com/mayeut/pybase64/blob/master/LICENSE
.. |pypi-status| image:: https://img.shields.io/pypi/v/pybase64.svg
:target: https://pypi.python.org/pypi/pybase64
.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pybase64.svg
.. |rtd-status| image:: https://readthedocs.org/projects/pybase64/badge/?version=stable
:target: http://pybase64.readthedocs.io/en/stable/?badge=stable
:alt: Documentation Status
.. |gha-status| image:: https://github.com/mayeut/pybase64/workflows/Build%20and%20upload%20to%20PyPI/badge.svg
:target: https://github.com/mayeut/pybase64/actions?query=workflow%3A%22Build+and+upload+to+PyPI%22
.. |codecov-status| image:: https://codecov.io/gh/mayeut/pybase64/branch/master/graph/badge.svg
:target: https://codecov.io/gh/mayeut/pybase64/branch/master
.. END OF SETUP
Fast Base64 implementation
==========================
|license-status| |pypi-status| |python-versions| |rtd-status| |gha-status| |codecov-status|
This project is a wrapper on `libbase64 <https://github.com/aklomp/base64>`_.
It aims to provide a fast base64 implementation for base64 encoding/decoding.
Installation
============
.. code::
pip install pybase64
Usage
=====
``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` with ``validate=True`` (or ``ignorechars=b""``) and ``padded=True`` when possible.
.. code:: python
import pybase64
print(pybase64.b64encode(b'>>>foo???', altchars='_:'))
# b'Pj4_Zm9vPz8:'
print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True))
# b'>>>foo???'
# Standard encoding helpers
print(pybase64.standard_b64encode(b'>>>foo???'))
# b'Pj4+Zm9vPz8/'
print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/'))
# b'>>>foo???'
# URL safe encoding helpers
print(pybase64.urlsafe_b64encode(b'>>>foo???'))
# b'Pj4-Zm9vPz8_'
print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_'))
# b'>>>foo???'
.. begin cli
A command-line tool is also provided. It has encode, decode and benchmark subcommands.
.. code::
usage: pybase64 [-h] [-V] {benchmark,encode,decode} ...
pybase64 command-line tool.
positional arguments:
{benchmark,encode,decode}
tool help
benchmark -h for usage
encode -h for usage
decode -h for usage
optional arguments:
-h, --help show this help message and exit
-V, --version show program's version number and exit
.. end cli
Full documentation on `Read the Docs <http://pybase64.readthedocs.io/en/stable/?badge=stable>`_.
Benchmark
=========
.. begin benchmark
Running Python 3.15.0rc1, Apple clang version 21.0.0 (clang-2100.1.1.101), macOS 26.5.2, Apple M1 Max
.. code::
pybase64 1.5.0 (C extension active - NEON)
bench: altchars=None, validate=True, padded=True
pybase64.encodebytes: 6595 MB/s (135,696 bytes -> 183,309 bytes)
pybase64.b64encode: 17492 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 9037 MB/s (180,928 bytes -> 135,696 bytes)
base64.encodebytes: 2386 MB/s (135,696 bytes -> 183,309 bytes)
base64.b64encode: 2653 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 2656 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, validate=True, padded=False
pybase64.b64encode: 17547 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 2521 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2656 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'', padded=False
pybase64.b64decode: 2510 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'\n', padded=True
pybase64.b64decode: 2370 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2087 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'\n', padded=False
pybase64.b64decode: 2365 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1964 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, validate=False, padded=True
pybase64.b64decode: 2369 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, validate=False, padded=False
pybase64.b64decode: 2361 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1982 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=True, padded=True
pybase64.b64encode: 10900 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 5974 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2675 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 1186 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=True, padded=False
pybase64.b64encode: 10798 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 2135 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2571 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 1154 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'', padded=True
pybase64.b64decode: 5770 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2629 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'', padded=False
pybase64.b64decode: 2201 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2606 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'\n', padded=True
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2069 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'\n', padded=False
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1882 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=False, padded=True
pybase64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1005 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=False, padded=False
pybase64.b64decode: 2081 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1031 MB/s (183,308 bytes -> 135,696 bytes)
.. end benchmark
.. begin changelog
Changelog
=========
1.5.0
------
- Speed-up translation on aarch64
- Fix invalid data successfully decoded when using altchars (slice ends with padding)
- Fix thread safety selecting codec
- Add ``padded`` and ``wrapcol`` parameters to ``b64encode``
- Add ``padded`` parameter to ``urlsafe_b64encode``
- Add ``padded`` parameter to ``b64decode`` & ``urlsafe_b64decode``
- ``urlsafe_b64decode`` now defaults to ``padded=False`` to align with Python 3.15 behavior
- Add ``ignorechars`` and ``canonical`` parameters to ``b64decode``
- Handle excess padding with the same behavior as CPython 3.15
- Reject non-ASCII strings in ``b64decode`` when ``validate=False``
- Deprecate accepting the ``+`` and ``/`` characters with an alternative alphabet when decoding
- Use ``ValueError`` instead of ``AssertionError`` on altchars length validation
- Add SBOM to PyPI wheels
- Publish python 3.15 wheels
- Drop python 3.8 support
- Stop publishing python 3.13t wheels
1.4.3
-----
- Publish Android Python 3.14 wheels
- Publish GraalPy v25 wheels
1.4.2
-----
- Update base64 library (Windows ARM64 Neon support)
- Publish Python 3.14 wheels
- Publish Linux riscv64 wheels
- Publish Android wheels
- Publish iOS wheels
- Publish GraalPy wheels
1.4.1
-----
- Publish PyPy 3.11 wheels
- Publish armv7l wheels
1.4.0
-----
- Publish python 3.13 wheels
- Add support for free-threaded builds
- Add MSYS2 support for C-extension
- Better logging on base64 build failure when C-extension build is optional
- Drop python 3.6 & 3.7 support
1.3.2
-----
- Update base64 library
- PyPy: fix wrong outcome with non C-contiguous buffer
1.3.1
-----
- Add missing py.typed marker
1.3.0
-----
- Update base64 library
- Add AVX512-VBMI implementation
- Rework extension build to remove adherence on distutils
- Publish python 3.12 wheels
- Documentation now uses furo theme
1.2.3
-----
- Update base64 library
- Publish python 3.11 wheels
1.2.2
-----
- Update base64 library
- Fix C extension build on musl distros
- Publish musllinux wheels
1.2.1
-----
- Publish PyPy 3.8 (pypy38_pp73) wheels
1.2.0
-----
- Release the GIL
- Publish CPython 3.10 wheels
- Drop python 3.5 support
1.1.4
-----
- Add macOS arm64 wheel
1.1.3
-----
- GitHub Actions: fix build on tag
1.1.2
-----
- Add PyPy wheels
- Add aarch64, ppc64le & s390x manylinux wheels
1.1.1
-----
- Move CI from TravisCI/AppVeyor to GitHub Actions
- Fix publication of Linux/macOS wheels
1.1.0
-----
- Add b64encode_as_string, same as b64encode but returns a str object instead of a bytes object
- Add b64decode_as_bytearray, same as b64decode but returns a bytarray object instead of a bytes object
- Speed-Up decoding from UCS1 strings
1.0.2
-----
- Update base64 library
- Publish python 3.9 wheels
1.0.1
-----
- Publish python 3.8 wheels
1.0.0
-----
- Drop python 3.4 support
- Drop python 2.7 support
0.5.0
-----
- Publish python 3.7 wheels
- Drop python 3.3 support
0.4.0
-----
- Speed-up decoding when validate==False
0.3.1
-----
- Fix deployment issues
0.3.0
-----
- Add encodebytes function
0.2.1
-----
- Fixed invalid results on Windows
0.2.0
-----
- Added documentation
- Added subcommands to the main script:
* help
* version
* encode
* decode
* benchmark
0.1.2
-----
- Updated base64 native library
0.1.1
-----
- Fixed deployment issues
0.1.0
-----
- First public release
.. end changelog
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
412 commits
356 commits
163 commits
120 commits
Python
63.6%
C
36.4%
.. SETUP VARIABLES
.. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg
:target: https://github.com/mayeut/pybase64/blob/master/LICENSE
.. |pypi-status| image:: https://img.shields.io/pypi/v/pybase64.svg
:target: https://pypi.python.org/pypi/pybase64
.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pybase64.svg
.. |rtd-status| image:: https://readthedocs.org/projects/pybase64/badge/?version=stable
:target: http://pybase64.readthedocs.io/en/stable/?badge=stable
:alt: Documentation Status
.. |gha-status| image:: https://github.com/mayeut/pybase64/workflows/Build%20and%20upload%20to%20PyPI/badge.svg
:target: https://github.com/mayeut/pybase64/actions?query=workflow%3A%22Build+and+upload+to+PyPI%22
.. |codecov-status| image:: https://codecov.io/gh/mayeut/pybase64/branch/master/graph/badge.svg
:target: https://codecov.io/gh/mayeut/pybase64/branch/master
.. END OF SETUP
Fast Base64 implementation
==========================
|license-status| |pypi-status| |python-versions| |rtd-status| |gha-status| |codecov-status|
This project is a wrapper on `libbase64 <https://github.com/aklomp/base64>`_.
It aims to provide a fast base64 implementation for base64 encoding/decoding.
Installation
============
.. code::
pip install pybase64
Usage
=====
``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` with ``validate=True`` (or ``ignorechars=b""``) and ``padded=True`` when possible.
.. code:: python
import pybase64
print(pybase64.b64encode(b'>>>foo???', altchars='_:'))
# b'Pj4_Zm9vPz8:'
print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True))
# b'>>>foo???'
# Standard encoding helpers
print(pybase64.standard_b64encode(b'>>>foo???'))
# b'Pj4+Zm9vPz8/'
print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/'))
# b'>>>foo???'
# URL safe encoding helpers
print(pybase64.urlsafe_b64encode(b'>>>foo???'))
# b'Pj4-Zm9vPz8_'
print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_'))
# b'>>>foo???'
.. begin cli
A command-line tool is also provided. It has encode, decode and benchmark subcommands.
.. code::
usage: pybase64 [-h] [-V] {benchmark,encode,decode} ...
pybase64 command-line tool.
positional arguments:
{benchmark,encode,decode}
tool help
benchmark -h for usage
encode -h for usage
decode -h for usage
optional arguments:
-h, --help show this help message and exit
-V, --version show program's version number and exit
.. end cli
Full documentation on `Read the Docs <http://pybase64.readthedocs.io/en/stable/?badge=stable>`_.
Benchmark
=========
.. begin benchmark
Running Python 3.15.0rc1, Apple clang version 21.0.0 (clang-2100.1.1.101), macOS 26.5.2, Apple M1 Max
.. code::
pybase64 1.5.0 (C extension active - NEON)
bench: altchars=None, validate=True, padded=True
pybase64.encodebytes: 6595 MB/s (135,696 bytes -> 183,309 bytes)
pybase64.b64encode: 17492 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 9037 MB/s (180,928 bytes -> 135,696 bytes)
base64.encodebytes: 2386 MB/s (135,696 bytes -> 183,309 bytes)
base64.b64encode: 2653 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 2656 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, validate=True, padded=False
pybase64.b64encode: 17547 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 2521 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2656 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'', padded=False
pybase64.b64decode: 2510 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'\n', padded=True
pybase64.b64decode: 2370 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2087 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, ignorechars=b'\n', padded=False
pybase64.b64decode: 2365 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1964 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, validate=False, padded=True
pybase64.b64decode: 2369 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=None, validate=False, padded=False
pybase64.b64decode: 2361 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1982 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=True, padded=True
pybase64.b64encode: 10900 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 5974 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2675 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 1186 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=True, padded=False
pybase64.b64encode: 10798 MB/s (135,696 bytes -> 180,928 bytes)
pybase64.b64decode: 2135 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64encode: 2571 MB/s (135,696 bytes -> 180,928 bytes)
base64.b64decode: 1154 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'', padded=True
pybase64.b64decode: 5770 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2629 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'', padded=False
pybase64.b64decode: 2201 MB/s (180,928 bytes -> 135,696 bytes)
base64.b64decode: 2606 MB/s (180,928 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'\n', padded=True
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 2069 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', ignorechars=b'\n', padded=False
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1882 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=False, padded=True
pybase64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1005 MB/s (183,308 bytes -> 135,696 bytes)
bench: altchars=b'-_', validate=False, padded=False
pybase64.b64decode: 2081 MB/s (183,308 bytes -> 135,696 bytes)
base64.b64decode: 1031 MB/s (183,308 bytes -> 135,696 bytes)
.. end benchmark
.. begin changelog
Changelog
=========
1.5.0
------
- Speed-up translation on aarch64
- Fix invalid data successfully decoded when using altchars (slice ends with padding)
- Fix thread safety selecting codec
- Add ``padded`` and ``wrapcol`` parameters to ``b64encode``
- Add ``padded`` parameter to ``urlsafe_b64encode``
- Add ``padded`` parameter to ``b64decode`` & ``urlsafe_b64decode``
- ``urlsafe_b64decode`` now defaults to ``padded=False`` to align with Python 3.15 behavior
- Add ``ignorechars`` and ``canonical`` parameters to ``b64decode``
- Handle excess padding with the same behavior as CPython 3.15
- Reject non-ASCII strings in ``b64decode`` when ``validate=False``
- Deprecate accepting the ``+`` and ``/`` characters with an alternative alphabet when decoding
- Use ``ValueError`` instead of ``AssertionError`` on altchars length validation
- Add SBOM to PyPI wheels
- Publish python 3.15 wheels
- Drop python 3.8 support
- Stop publishing python 3.13t wheels
1.4.3
-----
- Publish Android Python 3.14 wheels
- Publish GraalPy v25 wheels
1.4.2
-----
- Update base64 library (Windows ARM64 Neon support)
- Publish Python 3.14 wheels
- Publish Linux riscv64 wheels
- Publish Android wheels
- Publish iOS wheels
- Publish GraalPy wheels
1.4.1
-----
- Publish PyPy 3.11 wheels
- Publish armv7l wheels
1.4.0
-----
- Publish python 3.13 wheels
- Add support for free-threaded builds
- Add MSYS2 support for C-extension
- Better logging on base64 build failure when C-extension build is optional
- Drop python 3.6 & 3.7 support
1.3.2
-----
- Update base64 library
- PyPy: fix wrong outcome with non C-contiguous buffer
1.3.1
-----
- Add missing py.typed marker
1.3.0
-----
- Update base64 library
- Add AVX512-VBMI implementation
- Rework extension build to remove adherence on distutils
- Publish python 3.12 wheels
- Documentation now uses furo theme
1.2.3
-----
- Update base64 library
- Publish python 3.11 wheels
1.2.2
-----
- Update base64 library
- Fix C extension build on musl distros
- Publish musllinux wheels
1.2.1
-----
- Publish PyPy 3.8 (pypy38_pp73) wheels
1.2.0
-----
- Release the GIL
- Publish CPython 3.10 wheels
- Drop python 3.5 support
1.1.4
-----
- Add macOS arm64 wheel
1.1.3
-----
- GitHub Actions: fix build on tag
1.1.2
-----
- Add PyPy wheels
- Add aarch64, ppc64le & s390x manylinux wheels
1.1.1
-----
- Move CI from TravisCI/AppVeyor to GitHub Actions
- Fix publication of Linux/macOS wheels
1.1.0
-----
- Add b64encode_as_string, same as b64encode but returns a str object instead of a bytes object
- Add b64decode_as_bytearray, same as b64decode but returns a bytarray object instead of a bytes object
- Speed-Up decoding from UCS1 strings
1.0.2
-----
- Update base64 library
- Publish python 3.9 wheels
1.0.1
-----
- Publish python 3.8 wheels
1.0.0
-----
- Drop python 3.4 support
- Drop python 2.7 support
0.5.0
-----
- Publish python 3.7 wheels
- Drop python 3.3 support
0.4.0
-----
- Speed-up decoding when validate==False
0.3.1
-----
- Fix deployment issues
0.3.0
-----
- Add encodebytes function
0.2.1
-----
- Fixed invalid results on Windows
0.2.0
-----
- Added documentation
- Added subcommands to the main script:
* help
* version
* encode
* decode
* benchmark
0.1.2
-----
- Updated base64 native library
0.1.1
-----
- Fixed deployment issues
0.1.0
-----
- First public release
.. end changelog
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
412 commits
356 commits
163 commits
120 commits
Python
63.6%
C
36.4%