Replace Image.ANTIALIAS with Image.LANCZOS. It is the same resampling filter, and
Image.LANCZOS works on every Pillow release from 2.7 (2015) to 12.3.0, so the change is safe
whichever version your users have installed.
What the error looks like
We ran this pre-2023 snippet on Pillow 12.3.0:
from PIL import Image
img = Image.open("photo.jpg")
small = img.resize((400, 267), Image.ANTIALIAS)
Traceback (most recent call last):
File "example.py", line 4, in <module>
small = img.resize((400, 267), Image.ANTIALIAS)
^^^^^^^^^^^^^^^
AttributeError: module 'PIL.Image' has no attribute 'ANTIALIAS'
The same thing happens with Image.LINEAR and Image.CUBIC, which were removed in the same release.
Why ANTIALIAS was removed
The name is historical. Early PIL had one high-quality, convolution-based downscaling filter and called it
ANTIALIAS. In Pillow 2.7.0 the bilinear and bicubic filters were rewritten to use the same convolution approach,
so "antialias" no longer described anything special, and the filter got its proper name, LANCZOS.
ANTIALIAS stayed on as an alias for years before it was removed.
| Pillow version | What changed |
|---|---|
| 2.7.0 (2015) | Image.LANCZOS added; ANTIALIAS kept as an alias. |
| 9.1.0 (2022) | Image.Resampling enum added. ANTIALIAS, LINEAR, CUBIC (and, briefly, the other constants) deprecated with warnings. |
| 9.4.0 (2023) | Deprecation reversed for NEAREST, BILINEAR, BICUBIC, LANCZOS and friends: they are permanent. ANTIALIAS, LINEAR and CUBIC stay deprecated. |
| 10.0.0 (1 July 2023) | ANTIALIAS, LINEAR and CUBIC removed. Old code now raises AttributeError. |
One consequence that many tutorials still get wrong: you do not need Image.Resampling.LANCZOS.
The short constants were un-deprecated in 9.4.0, so Image.LANCZOS is not going away. The two spellings are the same filter value:
from PIL import Image
# Image.LANCZOS is a plain int; Image.Resampling.LANCZOS is an IntEnum member.
# They compare equal, and every Pillow function accepts either one.
print(repr(Image.LANCZOS), repr(Image.Resampling.LANCZOS))
print(Image.LANCZOS == Image.Resampling.LANCZOS)
1 <Resampling.LANCZOS: 1>
True
Fix your own code
Swap the constant. Output pixels are identical to what ANTIALIAS produced:
from PIL import Image
img = Image.open("photo.jpg")
small = img.resize((400, 267), Image.LANCZOS)
small.save("photo_small.jpg", quality=90)
print(small.size)
(400, 267)
The same applies anywhere a resample argument is accepted, such as thumbnail(), rotate() and transform():
from PIL import Image
img = Image.open("photo.jpg")
img.thumbnail((400, 400), Image.LANCZOS) # was: Image.ANTIALIAS
print(img.size)
(400, 267)
Every removed name and its replacement
| Removed in 10.0 | Use instead | Enum form (optional) |
|---|---|---|
Image.ANTIALIAS | Image.LANCZOS | Image.Resampling.LANCZOS |
Image.LINEAR | Image.BILINEAR | Image.Resampling.BILINEAR |
Image.CUBIC | Image.BICUBIC | Image.Resampling.BICUBIC |
Find every use in a project
Run this from your project root. It lists each file and line that still uses a removed name:
grep -rnE "Image\.(ANTIALIAS|LINEAR|CUBIC)\b" --include="*.py" .
./app/views.py:2:IMG_FILTER = Image.CUBIC
./app/utils/images.py:4: return img.resize((64, 64), Image.ANTIALIAS)
When the error comes from a library you didn't write
If the traceback ends inside site-packages/, the old constant is in a dependency. In order of preference:
- Upgrade the library. Most maintained projects fixed this in 2023. Check its changelog for "Pillow 10".
- Add a compatibility shim that restores the old names before the library is imported. This is a stop-gap for unmaintained code, not a long-term fix:
from PIL import Image
# Put this before importing the library that still uses the old names.
for old, new in {"ANTIALIAS": "LANCZOS", "LINEAR": "BILINEAR", "CUBIC": "BICUBIC"}.items():
if not hasattr(Image, old):
setattr(Image, old, getattr(Image, new))
# import some_old_library # now finds Image.ANTIALIAS again
print(Image.ANTIALIAS is Image.LANCZOS)
True
Why not just pin Pillow<10? Two reasons. First, you would miss three years of security fixes.
Second, it often does not install: Pillow 9.5.0 only published wheels up to Python 3.11. On Python 3.12 or 3.13,
pip install "Pillow<10" finds no compatible wheel and tries to compile Pillow from source, which fails
on most machines without a C compiler and image library headers. We checked: on Python 3.13 the oldest Pillow pip will
install from a wheel is 10.4.0.
Does LANCZOS still give the best quality?
For downscaling photos, Lanczos is the sharpest of Pillow's filters, and it is what ANTIALIAS always meant.
Here is a 1200 px "zone plate" (rings that get finer towards the edges) shrunk to 300 px with each filter.
Nearest-neighbour invents dozens of false ring centres: that is aliasing. Bilinear leaves faint ghost rings, bicubic
fewer, and Lanczos keeps the real rings in the middle crisp while suppressing almost all of the false detail:
from PIL import Image, ImageDraw, ImageFont
src = Image.open("rings.png") # 1200x1200 zone plate
font = ImageFont.load_default(size=22)
names = ["NEAREST", "BILINEAR", "BICUBIC", "LANCZOS"]
sheet = Image.new("L", (4 * 300, 340), 255)
for i, name in enumerate(names):
small = src.resize((300, 300), getattr(Image, name))
sheet.paste(small, (i * 300, 0))
ImageDraw.Draw(sheet).text((i * 300 + 150, 320), name, fill=0, font=font, anchor="mm")
sheet.save("filters.png")
If you never passed a filter at all, resize() already defaults to BICUBIC, and
thumbnail() uses BICUBIC with a fast reducing_gap pre-shrink. Both are good defaults;
pass Image.LANCZOS only when you want the extra sharpness.
Check which Pillow you have
python -c "import PIL; print(PIL.__version__)"
12.3.0
Anything 10.0 or newer has no ANTIALIAS. If the version printed is not the one you expected, you may be running a
different interpreter than the one you installed into; see No module named 'PIL'
for how to check.
Related
The outputs and images on this page are the real results of running every example with Pillow 12.3.0 on Python 3.13 (Linux) on 2026-10-15. Every example is also re-run automatically on macOS (Darwin 25.6.0, Pillow 12.3.0), Linux (Linux 6.17.0-1022-azure, Pillow 12.3.0), Windows (Windows 2025Server, Pillow 12.3.0); the line under each example shows the result per operating system. The DejaVu Sans font files sit next to each script so font examples behave the same everywhere. Sample photos: NASA/Sam Lott, public domain. Spotted something wrong? Tell us.