All formats

Pillow

LanguagePython
LicenseMIT-CMU (permissive)
Repositorygithub.com/python-pillow/Pillow
DocumentationAVIF in the Pillow handbook
Depends onlibavif with dav1d and libaom (included in the wheels from Pillow 11.3)
Read / writeyes / yes, 8-bit only; still and animated, alpha, Exif/XMP/ICC

Pillow is the standard imaging library for Python. AVIF support arrived in 11.2.1 for builds from source and is in the PyPI wheels since 11.3, using libavif with dav1d for decoding and libaom for encoding. Opening and saving AVIF works like any other format.

Pillow decodes every AVIF to 8-bit RGB or RGBA and saves only 8-bit AVIF, so 10/12-bit and HDR precision is lost. Use pyvips when you need high bit depth.

Installation#

Shell
pip install --upgrade Pillow

Check that your build has AVIF:

Python
from PIL import features
print(features.check("avif"))  # True

Basic usage: convert JPEG to AVIF and back#

Python
from PIL import Image

with Image.open("photo.jpg") as im:
    print(im.size, im.mode)
    im.save("photo.avif", quality=60)

with Image.open("photo.avif") as im:
    print(im.format, im.size, im.mode)  # AVIF (w, h) RGB
    im.save("photo.png")

How to set AVIF quality, speed and chroma subsampling#

Python
from PIL import Image

with Image.open("screenshot.png") as im:
    im.save(
        "screenshot.avif",
        quality=70,            # 0..100, default 75
        speed=4,               # 0 (slowest, smallest) .. 10 (fastest), default 6
        subsampling="4:4:4",   # 4:2:0 (default), 4:2:2, 4:4:4 or 4:0:0
    )

Use 4:4:4 for screenshots, text and graphics with sharp colored edges.

How to get AVIF width and height without decoding#

Image.open reads only the header; pixels are decoded when you access them:

Python
from PIL import Image

with Image.open("photo.avif") as im:
    print(im.width, im.height, im.mode, getattr(im, "n_frames", 1))

How to keep Exif and the ICC profile when converting#

Python
from PIL import Image

with Image.open("photo.jpg") as im:
    im.save(
        "photo.avif",
        quality=60,
        exif=im.info.get("exif"),
        icc_profile=im.info.get("icc_profile"),
    )

How to create an animated AVIF#

Python
from PIL import Image

frames = [Image.open(f"frame{i}.png") for i in range(10)]
frames[0].save(
    "anim.avif",
    save_all=True,
    append_images=frames[1:],
    duration=100,  # milliseconds per frame, or a list
    quality=50,
)

How to read the frames of an animated AVIF#

Python
from PIL import Image, ImageSequence

with Image.open("anim.avif") as im:
    for i, frame in enumerate(ImageSequence.Iterator(im)):
        frame.load()
        print(i, frame.size, frame.info.get("duration"))

Tips#