How to resize and compress images in Python with the TinyPNG API

Learn how to use the TinyPNG API in Python to bulk resize and compress images to improve site performance, SEO, and reduce bandwidth costs.

How to resize and compress images in Python with the TinyPNG API
Picture by Dollar Gill, Unsplash.
3 minutes to read

Large, uncompressed images slow down your site, increase bandwidth costs, harm the user experience, and impact search engine rankings. In this project, I’ll show you how you can bulk resize and compress over-sized images to save space and improve your site’s performance.

Load the packages

We’ll be using the os package for loading images from directories, Pandas for displaying the results of our image compression, and the tinify package from TinyPNG. This “freemium” image compression service is great for reducing file sizes and rescaling images.

import os
import tinify
import pandas as pd

Get a TinyPNG API key

While you can use the web frontend of TinyPNG for free and without registration, you’ll need a free API key to use its API. This lets you compress 500 images per month, so is only suitable for smaller volumes of work, but it’s cheap to upgrade.

tinify.key = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"

Resize and compress the images

Next, we’ll use os.listdir() to return a list called images containing the filename of each of the files found in the posts directory. Then we'll create a Pandas dataframe in which to store the results of compression, and we'll loop over the files in the images list using a for` loop.

We’ll use source = tinify.from_file("posts/" + image) to fetch the file, then source.resize() to scale each image to 1000 pixels wide (constraining the height proportions), we’ll save the compressed file to the compressed directory and use os.path.getsize() to get the size before and after compression, which we’ll append to the dataframe.

images = os.listdir('posts')

df = pd.DataFrame(columns = ['image', 'size_before', 'size_after', 'saving'])

for image in images:
    source = tinify.from_file("posts/" + image)
    resized = source.resize(method="scale", width=1000)
    resized.to_file("compressed/" + image)
    size_before = os.path.getsize("posts/" + image)
    size_after = os.path.getsize("compressed/" + image)
    row = {
        'image': image,
        'size_before': size_before,
        'size_after': size_after,
        'saving': size_before - size_after
    df = df.append(row, ignore_index=True)

After a few minutes, TinyPNG will have compressed all the images in our posts directory and filled the compressed directory with images that look the same but have a fraction of the original file size. Upload them to the web server with the original filenames and your site will be faster, customers will be happier, bandwidth costs will fall, and SEO scores will improve.

Matt Clarke, Friday, March 12, 2021

Matt Clarke Matt is an Ecommerce and Marketing Director who uses data science to help in his work. Matt has a Master's degree in Internet Retailing (plus two other Master's degrees in different fields) and specialises in the technical side of ecommerce and marketing.