Latest Release: v12.2.0 — Security patches, WEBP improvements | v11.2.1 v10.4.0 | Python 3.9 – 3.13 supported
v12.2.0 Available Now

The Python Imaging
Library (PIL) Fork.

Python Pillow is the industry standard for image processing in Python. Open, resize, filter, convert, draw, and analyze images with a clean, expressive API — all in pure Python.

Install / Download Live Demo GitHub

Trusted by the ecosystem backing modern web & AI

Django FastAPI PyTorch Hugging Face Scikit-learn Ubuntu
12K+
GitHub Stars
30+
Image Formats
200M+
PyPI Downloads / Month
$0
Cost — MIT Licensed

Core Capabilities.

Everything you need to manipulate local and remote images inside Python pipelines.

🗂️

Extensive Format Support

Seamlessly open, read, and write JPEG, PNG, WEBP, GIF, TIFF, BMP, ICO, PSD, and 25+ more formats. Batch-convert massive ML datasets with single-line format migrations.

📐

Geometric Transforms

Resize, crop, rotate, flip, and transpose images. Use high-quality Lanczos resampling to retain visual fidelity at any scale.

🎨

Image Filtering

Apply BLUR, CONTOUR, SHARPEN, EDGE_ENHANCE, FIND_EDGES, EMBOSS, and custom kernel filters via the ImageFilter module.

✏️

Programmatic Drawing

Draw polygons, arcs, rectangles, and overlay TrueType/OpenType text with ImageDraw. Automate watermarks, captions, and thumbnail overlays at scale.

🧩 Core Modules.

Pillow's power comes from its modular design. Each module handles a distinct area of image processing.

📷

Image

The central class. Open, create, save, convert, resize, and transform images. Every pipeline starts here.

open()save()resize()crop()convert()
View Reference →
✏️

ImageDraw

Draw 2D graphics onto images. Supports lines, rectangles, ellipses, polygons, and text rendering.

line()rectangle()ellipse()text()
View Reference →
🔮

ImageFilter

Pre-built filters including GaussianBlur, UnsharpMask, MedianFilter, and custom kernel convolutions.

GaussianBlurSHARPENEDGE_ENHANCE
View Reference →

ImageEnhance

Adjust Brightness, Contrast, Color saturation, and Sharpness using a simple factor-based API.

BrightnessContrastColorSharpness
View Reference →
🔧

ImageOps

High-level operations: autocontrast, equalize, flip, grayscale, pad, fit, contain, and invert.

autocontrast()equalize()fit()grayscale()
View Reference →
🔠

ImageFont

Load TrueType (TTF) and OpenType (OTF) fonts for high-quality text rendering in generated images.

truetype()load_default()getbbox()
View Reference →
🎛️

ImageChops

Channel operations: add, subtract, multiply, difference, composite — pixel-level arithmetic between images.

add()multiply()difference()
View Reference →
📊

ImageStat

Compute statistics (mean, median, RMS, standard deviation, extrema) over entire images or pixel bands.

meanmedianrmsextrema
View Reference →

📥 How to Install Pillow.

Zero to processing in minutes. Select your operating system below.

Step 1

Install via PIP

Windows supplies pre-compiled binary wheels — no Visual Studio required. Run in PowerShell.

powershell
$python -m pip install --upgrade Pillow
Verify

Verify Installation

Open the Python REPL and ensure PIL is detected successfully.

python
>>>import PIL
>>>print(PIL.__version__)
Step 1

Install Library

Pillow provides universal wheels for both Apple Silicon (M1/M2/M3) and Intel Macs.

terminal
$python3 -m pip install --upgrade Pillow
Optional

Add JPEG2000 / LibTIFF

Use Homebrew to add optional codec support before installing Pillow.

terminal
$brew install libjpeg libtiff openjpeg
Step 1

System Dependencies

Install C libraries needed for full format support.

bash
$sudo apt-get install libjpeg-dev zlib1g-dev
Step 2

Install via pip

Install Pillow into your current Python environment.

bash
$pip install Pillow
Alt

System Package

For system-wide install without a virtual environment.

bash
$sudo apt-get install python3-pil
Step 1

Create Virtual Env

Recommended: keep your project dependencies isolated.

shell
$python -m venv venv
$source venv/bin/activate # Linux/macOS
$venv\Scripts\activate # Windows
Step 2

Install Pillow

With the environment active, install Pillow normally.

shell
(venv) $pip install Pillow
Conda

Install via Conda

Available in both the defaults and conda-forge channels.

conda
$conda install -c conda-forge pillow
Verify

Verify in Jupyter

Pillow integrates natively with Jupyter Notebook for inline image display.

jupyter
[1]:from PIL import Image
img = Image.open("photo.jpg")
img # renders inline in Jupyter

📦 Format Support Matrix.

All 30+ image formats supported across read, write, and animation dimensions.

⚡ Quick Code Cheatsheet

The most frequently used Python instructions for daily image processing tasks.

Open & Inspect

Load an image and verify its size, mode, and format.

img = Image.open('file.jpg')
print(img.size, img.format, img.mode)

Generate Thumbnails

Resize preserving aspect ratio in-place.

img.thumbnail((400, 400))
img.save('thumb.jpg')

Convert to WEBP

Save heavy PNGs as highly compressed lossless WEBP.

img = img.convert("RGB")
img.save('file.webp')

Crop Geometry

Define a box tuple (left, upper, right, lower) to slice.

area = (100, 100, 400, 400)
cropped = img.crop(area)

Apply a Filter

Blur, sharpen, find edges — one-line filter application.

from PIL import ImageFilter
blurred = img.filter(ImageFilter.GaussianBlur(radius=3))

Draw Text on Image

Overlay text using ImageDraw and a loaded font.

draw = ImageDraw.Draw(img)
draw.text((10, 10), "Hello!", fill="white")

Enhance Brightness

Adjust brightness, contrast, color, or sharpness by a factor.

from PIL import ImageEnhance
bright = ImageEnhance.Brightness(img).enhance(1.5)

Read EXIF Data

Extract camera metadata embedded in JPEG images.

exif = img._getexif()
print(exif)

📖 Real-World Recipes.

Copy–paste solutions for the most common Pillow use cases. Every recipe is production-ready.

🗂️

Batch Resize for Web

Automation

Resize every image in a folder to 800×600 max bounding box, preserving aspect ratio. Ideal for pre-processing ML datasets or web asset pipelines.

batch_resize.py
from PIL import Image import os, pathlib src = pathlib.Path("./images") dst = src / "resized" dst.mkdir(exist_ok=True) for fp in src.glob("*.jpg"): img = Image.open(fp) img.thumbnail((800, 600)) img.save(dst / fp.name)
💧

Watermark 1000 Images

Branding

Overlay semi-transparent text or logo watermarks on every image in a directory. Uses composite blending for professional results.

watermark.py
from PIL import Image, ImageDraw, ImageFont def add_watermark(path, text="© MyBrand"): img = Image.open(path).convert("RGBA") overlay = Image.new("RGBA", img.size, (0,0,0,0)) draw = ImageDraw.Draw(overlay) draw.text((20, 20), text, fill=(255,255,255,120)) img = Image.alpha_composite(img, overlay) img.save(path.replace(".png", "_wm.png"))
🔍

Extract EXIF Metadata

Analysis

Read camera metadata from JPEG photos: GPS coordinates, make/model, ISO, shutter speed, and focal length — decoded to human-readable values.

read_exif.py
from PIL import Image from PIL.ExifTags import TAGS img = Image.open("photo.jpg") exif_data = img._getexif() if exif_data: for tag_id, value in exif_data.items(): tag = TAGS.get(tag_id, tag_id) print(f"{tag:25}: {value}")
📱

Generate Social Cards

Content

Programmatically create Open Graph / Twitter card images. Draw a gradient background, overlay your title text, and export as optimized JPEG.

social_card.py
from PIL import Image, ImageDraw, ImageFont img = Image.new("RGB", (1200, 630), (30, 30, 46)) draw = ImageDraw.Draw(img) font = ImageFont.truetype("Inter.ttf", 60) draw.text( (60, 250), "My Article Title", fill="white", font=font ) img.save("og_card.jpg", quality=95)
✂️

Auto-Crop to Content

Transform

Use getbbox() to automatically detect non-white/non-black borders and crop the image to its real content region.

auto_crop.py
from PIL import Image, ImageOps img = Image.open("scan.png").convert("RGB") # Remove white border/padding automatically inverted = ImageOps.invert(img) bbox = inverted.getbbox() if bbox: cropped = img.crop(bbox) cropped.save("cropped.png")
🔄

Batch PNG → WEBP

Conversion

Convert an entire directory of PNG files to space-efficient WEBP format. Typically reduces file size by 25–34% without visible quality loss.

png_to_webp.py
from PIL import Image import pathlib for fp in pathlib.Path(".").glob("*.png"): img = Image.open(fp).convert("RGB") out = fp.with_suffix(".webp") img.save(out, "WEBP", quality=85, method=6) print(f"Saved {out}")

⚙️ Visual Script Generator

Toggle the operations you need — copy a unified, ready-to-run processing pipeline.

pipeline.py

🖼️ Live Image Playground.

Apply Pillow-equivalent effects instantly in your browser. Toggle filters and see the result in real time.

Image Effects

100%
100%
100%
0px
0

Presets

Pillow playground demo image
Live Preview
Equivalent Pillow Code:

                

📊 Pillow vs The Alternatives.

See how Pillow stacks up against other Python image processing libraries.

Feature Pillow ✅ OpenCV Wand (ImageMagick) scikit-image imageio
Pure Python API ✅ Yes ❌ C++ bindings ❌ C bindings ✅ Yes ✅ Yes
Ease of Use ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Format Support 30+ formats ~20 formats 200+ formats ~15 formats ~20 formats
pip install size ~3 MB ~50 MB ~30 MB ~20 MB ~1 MB
Drawing / Text ✅ ImageDraw ✅ cv2.putText ✅ Drawing ❌ Limited ❌ None
Thumbnail Generation ✅ One line ⚠️ Manual ✅ Yes ⚠️ Manual ⚠️ Manual
ML / NumPy Integration ✅ np.array(img) ✅ Native arrays ⚠️ Limited ✅ Native ✅ Arrays
License MIT (HPND) Apache 2.0 MIT BSD BSD
Best For General purpose Computer vision Complex transforms Scientific analysis I/O only

💡 Common Errors & Fixes.

The top developer pain points when working with Pillow — with exact solutions.

ModuleNotFoundError

No module named 'PIL'

Cause: Pillow is not installed in the current Python environment.

Fix: Install via pip. The package is called Pillow but imports as PIL.

powershell
$pip install Pillow
# Then use: from PIL import Image
OSError

cannot identify image file

Cause: The file extension doesn't match the actual format, or the file is corrupt/truncated.

Fix: Verify the actual format and pass the explicit format parameter.

python
>>># Check actual format:
with open('file', 'rb') as f: print(f.read(4))
# Force format:
img = Image.open('file', formats=['JPEG'])
DecompressionBombWarning

Image may be a decompression bomb

Cause: Pillow's security limit blocks images larger than 178 million pixels by default to prevent DoS attacks.

Fix: Raise or disable the limit (only for trusted sources).

python
>>>Image.MAX_IMAGE_PIXELS = None # disable
# or raise limit:
Image.MAX_IMAGE_PIXELS = 500_000_000
Orientation Issue

Image appears rotated after opening

Cause: Camera stores orientation in EXIF tag but Pillow does not auto-rotate on open.

Fix: Use ImageOps.exif_transpose() to apply EXIF rotation automatically.

python
>>>from PIL import ImageOps
img = Image.open("photo.jpg")
img = ImageOps.exif_transpose(img)
OSError

cannot write mode RGBA as JPEG

Cause: JPEG does not support transparency (alpha channel). The image has 4 channels (RGBA) instead of 3 (RGB).

Fix: Convert to RGB before saving as JPEG, or use PNG for transparency.

python
>>>img = img.convert("RGB") # drop alpha
img.save("output.jpg", quality=95)
MemoryError

Out of memory when processing large images

Cause: Large images are loaded entirely into RAM before processing. A 100 MP TIFF can consume 1–2 GB uncompressed.

Fix: Use draft mode for loading, process in tiles, or downscale before processing.

python
>>># Load reduced version (JPEG only):
img.draft("RGB", (800, 600))
img.load()

Frequently Asked Questions

Everything developers need to know about Pillow in Python.

What is Pillow exactly?

Python Pillow is an open-source library that adds support for opening, manipulating, and saving many different image file formats. As the active fork of the original Python Imaging Library (PIL), Pillow is the foundational tool for image processing in Python — no complex C dependencies required for most operations.

What is the difference between PIL and Pillow?

PIL (Python Imaging Library) is the original, now-discontinued library that stopped supporting Python 3. Pillow is the actively maintained, drop-in compatible fork. It adds Python 3 support, security patches, new format support (WEBP, AVIF), and modern API improvements. You install Pillow but import it as PIL.

How do I fix "No module named PIL"?

Run pip install Pillow. Even though the package is called Pillow, the import namespace is PIL for backward compatibility. Always use from PIL import Image in your code. If you're using a virtual environment, ensure it is activated first.

How do I check which version of Pillow I have?

Run in Python: import PIL; print(PIL.__version__). Or from your terminal: python -m PIL which will print the version and feature support matrix. You can also run pip show Pillow from the command line.

What image formats does Pillow support?

Pillow supports 30+ formats including JPEG, PNG, WEBP, GIF (animated), TIFF, BMP, ICO, EPS, PSD (Adobe Photoshop), PDF reading, PPM, PCX, and more. Some formats like AVIF require optional system libraries. Use Image.registered_extensions() to see all available formats in your installation.

Can Pillow work with NumPy arrays?

Yes. You can convert between Pillow Images and NumPy arrays easily: arr = numpy.array(img) to convert to array, and img = Image.fromarray(arr) to convert back. This makes Pillow ideal as a preprocessing layer before feeding images into PyTorch, TensorFlow, or scikit-learn models.

Can Pillow read and create animated GIFs?

Yes. Use img.seek(frame_number) to iterate through GIF frames. To create an animated GIF, open all frames as a list and use img.save('output.gif', save_all=True, append_images=[...], duration=100, loop=0). Pillow can also read animated WEBP and TIFF files.

Is Pillow fast enough for production use?

Pillow is implemented in C via libjpeg, zlib, and other native codecs — making it significantly faster than pure Python alternatives. For high-throughput pipelines, use img.draft() for JPEG draft loading, process multiple images with concurrent.futures.ThreadPoolExecutor, and use img.thumbnail() instead of img.resize() to avoid unnecessary upscaling.

Does Pillow support WEBP and AVIF?

WEBP is fully supported for reading, writing, and animated WEBP files. AVIF support was added in Pillow 9.1.0 but requires libavif to be installed on your system. To check: PIL.features.check('avif'). Modern binary wheels on PyPI include WEBP support out of the box.

What is the Pillow license? Is it free for commercial use?

Pillow uses the HPND (Historical Permission Notice and Disclaimer) license — a permissive open-source license similar to MIT. It is completely free for commercial use, closed-source projects, and any application. No attribution is required in your product, though credit is always appreciated by the community.