# Image optimisation plugins compared honestly

> ShortPixel, Imagify, EWWW, Smush, Optimole, TinyPNG and the core Modern Image Formats plugin, compared by what they actually do, what they cost and what none of them fixes. Pick one and measure the result.

Updated 2026-09-25 · WordPress & WooCommerce · HTML version: https://getreport.app/guides/image-optimisation-plugins-compared-honestly

Every WordPress image plugin promises "up to 80 % smaller images" and every one of them is telling a version of the truth. The differences that matter are where the work happens (your server or theirs), what you pay per image, which formats come out, and whether the plugin also fixes the size of the image the browser downloads. This guide compares the common plugins by mechanism instead of by marketing, shows what none of them can fix, and walks through one setup with a before-and-after measurement.

## Quick answer

- Any of these plugins solves the "2 MB JPEG straight from the camera" problem. The differences are cost model and where the processing runs.
- **Free and unlimited, on your server:** EWWW Image Optimizer (local mode) or WordPress's own Modern Image Formats plugin (WebP/AVIF on upload, nothing else).
- **Cloud with a quota:** ShortPixel (credits per image), Imagify (megabytes per month), TinyPNG (compressions per month), Smush Pro (subscription).
- **CDN that rewrites your image URLs:** Optimole and ShortPixel Adaptive Images; nothing in your media library changes.
- None of them fix an image placed at 4000 px in a page builder background, an image loaded from another site, or a hero that is lazy-loaded. Those are theme and layout fixes.
- Measure with the [image size checker](https://getreport.app/tools/image-size-checker) before and after; the file sizes in the table are the proof.

## Why image optimisation matters

Images are most of the bytes on most pages, and one unoptimised upload can outweigh everything else. A photo uploaded from a phone is 3–6 MB and 4000 px wide; a product thumbnail displayed at 300 px needs about 20 KB. WordPress helps by generating smaller sizes on upload and, since 5.3, by scaling anything over 2560 px down, but the generated sizes are still JPEGs at the original quality, and the theme does not always pick the right one.

The cost lands on mobile. On a 4G connection, a 1.5 MB hero image takes over a second to arrive and pushes Largest Contentful Paint past Google's 2.5 s threshold on its own. It also costs visitors data and costs you bandwidth. An image plugin is the cheapest speed fix a WordPress site has, provided it is set up to do the two things that count: shrink the bytes and serve a modern format.

Plugins are good at the part that scales badly for humans: converting thousands of existing files and every future upload without anyone remembering to. They are less good at the layout side, which is where the honest comparison starts.

## How getReport checks it

> **Free tool:** [Image size checker](https://getreport.app/tools/image-size-checker): List every image on a page with its file size, format, real pixel dimensions and the size it is displayed at. Find the 2 MB hero, the 1600-pixel thumbnail and the images with no width and height.

The checker requests up to 100 `<img>` sources from the page, reads the first 64 KB of each to get the format and pixel dimensions, and takes the file size from `Content-Length`. Together with the `width`, `height`, `loading` and `srcset` attributes in the HTML, that gives a table of every image with its weight, its real dimensions and the size it is displayed at. Chromium then loads the page so the total includes CSS backgrounds, and Lighthouse adds its format and sizing estimates.

![The images table for a page with heavy images: each file with its size in KB, its pixel dimensions and the displayed size, with an oversized chip on the ones served at more than twice their slot and a heavy chip on the ones over 300 KB](https://getreport.app/guides/img/image-optimisation-plugins-compared-honestly/images.webp "Sort by size: the top three rows are usually the whole problem.")

Four findings come out of it, and they map onto what a plugin can and cannot do:

> **Check: Heavy image files.** A single image over a few hundred kilobytes takes longer to download on mobile than the rest of the page. Uploading the original camera file is the usual cause.
>
> 1. Export each listed image at the size it is displayed and save it as WebP or AVIF at about 80 % quality.
> 2. Let your CMS or CDN resize on upload so this does not come back with the next photo.

This one is measured from the actual files, with a 300 KB limit. A compression plugin fixes it directly.

> **Check: Images are served in modern formats (WebP or AVIF).** WebP and AVIF are 25–50 % smaller than JPEG and PNG at the same quality. Smaller images load faster and cost visitors less data.
>
> 1. Convert images to WebP or AVIF and serve them with <picture> or content negotiation.
> 2. WordPress: enable WebP/AVIF in your image plugin or CDN (Imagify, ShortPixel, Cloudflare Polish); Shopify does this automatically for its CDN.

This is Lighthouse's estimate of what WebP or AVIF would save. A plugin with format conversion fixes it, but only if the conversion is actually served, which is the step people miss (see step 4 below).

> **Check: Images are sized for how they are displayed.** Sending a 2000 px photo to a 400 px slot wastes most of the bytes. Responsive images let the browser pick the right size for each screen.
>
> 1. Add srcset and sizes to <img> so phones get small versions; most CMSs generate the sizes for you.
> 2. Resize the originals to the largest size you actually display.

Lighthouse compares each image's natural size with its rendered size. Resize-on-upload and a working `srcset` fix it; compression alone does not.

> **Check: Offscreen images are lazy-loaded.** Images far below the fold compete for bandwidth with the ones visitors see first. Lazy loading defers them until they scroll into view.
>
> 1. Add loading="lazy" to images below the fold — but never to the hero/LCP image.
> 2. WordPress adds it by default since 5.5; check your theme or slider has not removed it.

WordPress adds `loading="lazy"` itself. A plugin's lazy-load feature is only needed when the theme or a slider removed it, and it must never touch the hero image.

## The plugins, by mechanism

The table is what each plugin does, not a ranking. All of them compress JPEG and PNG on upload and can process the existing library in bulk.

| Plugin | Where it runs | Cost model | Formats | Resize on upload | Also does |
| --- | --- | --- | --- | --- | --- |
| ShortPixel Image Optimizer | Cloud | Credits per image, monthly or one-off | WebP, AVIF | Yes | Backups of originals; a separate Adaptive Images plugin serves from a CDN |
| Imagify | Cloud | Free monthly allowance, then plans by megabytes | WebP, AVIF | Yes | From the makers of WP Rocket; the two integrate |
| EWWW Image Optimizer | Your server (free) or their API (paid) | Local mode free with no quota; API and Easy IO CDN paid | WebP locally; more via API | Yes | Serves WebP with `<picture>` rewriting or server rewrite rules |
| Smush | Cloud | Free tier with lossless compression and a per-file size limit; Pro subscription | WebP/AVIF in Pro | Yes | Lazy load; CDN in Pro |
| Optimole | Cloud CDN | Plans by monthly visits; free tier | WebP, AVIF, on the fly | Not needed: resizes per request | Replaces image URLs; media library untouched |
| Compress JPEG & PNG images (TinyPNG) | Cloud | Free monthly allowance of compressions, then per image | JPEG, PNG compression | Yes | Simple; one setting screen |
| Modern Image Formats (WordPress Performance Team) | Your server (free) | Free, no quota | WebP; AVIF where the server supports it | No (core already scales over 2560 px) | New uploads only; `<picture>` output optional |

### Local versus cloud

Local plugins compress with binaries on your web server: no bill and no upload to a third party, but bulk-optimising 5,000 images takes CPU your visitors are also using, and shared hosts sometimes lack the binaries or the memory. Cloud plugins send each image to the vendor and cost per image or per megabyte. For a store uploading 50 product photos a week the cloud bill is small; for a photography site uploading gigabytes, local is the only affordable option.

### Lossy versus lossless

Lossless compression removes metadata and re-encodes without changing a pixel: 5–20 % smaller, invisible. Lossy re-encodes at a lower quality: 40–80 % smaller, and at the vendors' default settings (roughly quality 80) the difference is not visible on a normal screen. ShortPixel's "glossy" and Imagify's default sit between. Choose lossy for everything except images where exact pixels matter (screenshots with small text, logos with flat colour, which should be SVG or PNG anyway). Smush's free tier and EWWW's free local mode are lossless; that is the main thing the free tiers hold back.

### Which format

WebP is supported by every current browser and cuts 25–35 % from a JPEG at the same visible quality. AVIF is smaller again but slower to encode and, on some plugins, a paid option. The [WebP and AVIF guide](https://getreport.app/guides/modern-image-formats-webp-avif) has the quality settings; for a plugin the decision is just "WebP on, AVIF on if the plan includes it and the server can encode it".

### CDN-based plugins are a different product

Optimole and ShortPixel Adaptive Images do not change files in your library. They rewrite every image URL to point at their CDN, which resizes and converts each image for the requesting device on the fly, so they solve sizing as well as format, and they cover page-builder backgrounds because they rewrite CSS too. The trade-offs: images come from a third-party domain, the plan is priced by visits, and if you stop paying the URLs stop working until you deactivate the plugin.

## What none of them fixes

- **A 4000 px image used at 800 px** in a theme that requests the full size. Resize-on-upload caps the largest file (set it to 2560 px or the widest slot you have), but the theme still has to ask for the right size. Check the "Displayed" column against "Pixels" in the report's table; if they differ by more than 2×, it is a theme or `srcset` problem, covered in [Responsive images: srcset and sizes](https://getreport.app/guides/responsive-images-srcset-and-sizes).
- **Page-builder backgrounds.** Elementor, Divi and Beaver Builder set section backgrounds with CSS, which has no `srcset`, and most `<picture>`-based WebP delivery does not touch CSS. Server rewrite rules (EWWW's `.htaccess` method, or a CDN doing content negotiation) do.
- **Images from other domains.** Embedded product shots from a supplier, a partner's logo, a hotlinked chart. Nothing on your server can change them; download and upload, or accept them.
- **The lazy-loaded hero.** A lazy-load feature applied to every image delays the largest one and makes LCP worse. Every plugin has an exclusion; use it for the first image on the page. [Lazy loading done right](https://getreport.app/guides/lazy-loading-done-right) has the details.
- **Images that should not be images.** A 600 KB PNG of a headline, an icon set as PNG instead of SVG. Compression makes them smaller; replacing them makes them disappear.

## Step by step

One setup, using EWWW Image Optimizer because it is free with no quota, converts to WebP and can serve it without a CDN. The same steps apply to the others with different screen names.

### 1. Take a baseline

Run the image size checker on the home page and one product or post page. Save the report links. Note the total image weight, the number of files over 300 KB and the "Serve images in next-gen formats" saving.

### 2. Back up the uploads folder

Every plugin that compresses in place either keeps backups or offers to. Turn the backup option on for the first run, or copy `wp-content/uploads` yourself. Lossy compression cannot be undone without the original.

### 3. Set the compression and resize options

Settings → EWWW Image Optimizer, Basic tab:

- **Remove metadata**: on.
- **Resize images**: set a maximum width, 2560 px for a site with full-width heroes, 1600 px for a blog. Uploads wider than that are scaled down before anything else happens.
- **Lazy load**: leave it off unless the report says offscreen images load eagerly; WordPress already adds `loading="lazy"`.
- **WebP conversion**: on.

Cloud plugins have the same choices under different names: compression level (lossy/glossy/lossless in ShortPixel, Normal/Aggressive/Ultra in Imagify), "resize larger images" with a width, and "create WebP/AVIF versions".

### 4. Make sure the WebP versions are served

Creating a `.webp` next to each JPEG does nothing until the browser is sent it. EWWW offers two delivery methods:

**`<picture>` rewriting** (the "WebP delivery method" setting): the plugin wraps each `<img>` in a `<picture>` with a WebP source. Works on any host; misses CSS backgrounds.

**Server rewrite rules**: the server returns the `.webp` when the browser's `Accept` header includes it, for any image URL, including CSS backgrounds. On Apache the plugin inserts this into `.htaccess`; on nginx you add it yourself:

```nginx
# Serve .webp when it exists and the browser accepts it
map $http_accept $webp_suffix {
    default "";
    "~*image/webp" ".webp";
}

server {
    location ~* ^/wp-content/uploads/.+\.(png|jpe?g)$ {
        add_header Vary Accept;
        try_files $uri$webp_suffix $uri =404;
    }
}
```

The `Vary: Accept` header matters when a cache or CDN sits in front: without it, a cached WebP can be served to a browser that asked for JPEG.

### 5. Bulk-optimise the existing library

Media → Bulk Optimize (EWWW), or the equivalent screen in the other plugins. On a shared host, run it in the evening; a 3,000-image library takes an hour or two locally and minutes through a cloud API, and cloud plugins count every existing image against the quota.

### 6. Re-run the checker

Same two pages, a new report (the cache keeps results for 12 hours; use the re-run link). The table should show `webp` in the format column, no rows over 300 KB, and the next-gen formats finding passing. If "Images are larger than they are displayed" still fires, the remaining work is in the theme, not the plugin.

> **Watch out:**
> Do not run two image plugins at once. Two plugins compressing the same upload produce visible artefacts, two WebP delivery methods produce broken `<picture>` markup, and the second plugin's lazy load can override the first's exclusions. Deactivate the old one before activating the new one.

## Platform notes

### WordPress.com and managed hosts

WordPress.com and several managed hosts (WP Engine, Kinsta, SiteGround) already serve images through a CDN that converts to WebP on the fly. Check the report's format column before installing anything: if it already says `webp`, a plugin adds compression on upload but not conversion, and the free Modern Image Formats plugin may be all you need.

### WooCommerce

Product galleries are where the count adds up: five images per product, each in six sizes. The sizes WooCommerce generates are set under Appearance → Customize → WooCommerce → Product Images (600 px main image and 300 px thumbnails by default); set the plugin's resize limit to the largest size the zoom actually uses and let the plugin handle the rest. Optimole-style CDNs pay for themselves here because they pick the size per device.

## Verify

- The image size checker's table shows every row under 300 KB, formats as `webp` or `avif`, and no rows with the oversized chip.
- The next-gen formats, responsive images and offscreen images findings pass in the [speed test](https://getreport.app/tools/speed-test), and the LCP finding names a lighter element than before.
- `curl -sI -H "Accept: image/webp" https://example.com/wp-content/uploads/2026/09/hero.jpg | grep -i content-type` prints `image/webp` if the server rewrite method is in use.
- The originals still exist (backup folder or the `-original` files), so a bad compression run can be reverted.

## Common mistakes

- **Converting without serving.** The `.webp` files exist on disk and the browser never gets them. Turn on a delivery method and check the response's `Content-Type`.
- **Lazy-loading the hero.** LCP gets worse by the time it takes to scroll-trigger the load. Exclude the first image, or the whole first section, in the plugin's settings.
- **Compressing the originals with no backup, then changing your mind.** Lossy is permanent. Back up before the first bulk run.
- **Running the bulk optimiser during peak hours on shared hosting.** Visitors get slow pages and the run times out. Schedule it for the night or use a cloud plugin for the backlog.
- **Ignoring the sizing finding because the format finding passed.** A 1600 px WebP in a 300 px slot is still five times too big. Fix `srcset` and the theme's size choice.
