---
title: "WordPress Image Formats in 2026: What Core Does, and Bytes I Measured Myself"
url: https://adityaarsharma.com/wordpress-image-formats-webp-avif-2026/
date: 2026-09-28
modified: 2026-09-03
lang: en
author: "Aditya Sharma"
description: "WordPress 7.1 does not convert JPEGs to WebP. I read the source, then converted two real files at core's own quality defaults. AVIF lost one of them."
categories:
  - "WordPress"
image: https://adityaarsharma.com/wp-content/uploads/2026/09/60985c91-fa78-4d67-a530-4a2fffd3e36e_2912x1632-1024x574.webp
word_count: 2098
---

# WordPress Image Formats in 2026: What Core Does, and Bytes I Measured Myself

WordPress 7.1 does not convert your JPEGs to WebP. It does not convert them to AVIF either.

The default output format map in core is four lines long and it maps HEIC to JPEG, which is the opposite direction from the one everybody assumes.

Here is the whole function, from `wp-includes/media.php` in the 7.1 tarball I downloaded on 3 September 2026:

![AVIF beat WebP on the screenshot and lost on the photograph.](https://adityaarsharma.com/wp-content/uploads/2026/09/60985c91-fa78-4d67-a530-4a2fffd3e36e_2912x1632-scaled.png)
`function wp_get_image_editor_output_format( $filename, $mime_type ) {
$output_format = array(
'image/heic' => 'image/jpeg',
'image/heif' => 'image/jpeg',
'image/heic-sequence' => 'image/jpeg',
'image/heif-sequence' => 'image/jpeg',
);
return apply_filters( 'image_editor_output_format', $output_format, $filename, $mime_type );
}`
A JPEG upload is not in that map, so it comes out the other end as a JPEG. A PNG comes out as a PNG. The docblock records the only change that ever happened:

*@since 6.7.0 The default was changed from an empty array to an array containing the HEIC/HEIF images mime types*. Before 6.7 the default was nothing at all.

So if a post tells you core generates WebP automatically now, that post is wrong, and it has been wrong through several release cycles.

What core actually gives you is the ability to *read* WebP and AVIF, to serve them if you upload them, and one filter to change the conversion policy. The conversion itself is a plugin's job.

On this page

- What core does do with the modern formats- The storage multiplication, counted on a real upload- Honest byte comparisons, measured on real files- Why the two files disagree, which is the part worth keeping- The cost nobody puts in the comparison: encode time- The plugin that actually does the conversion- Doing it yourself with the filter, and when not to- What does not work- One thing to do next- Resources

## What core does do with the modern formats

### Three things core does do

**It accepts them as uploads.** `image/avif` and `image/webp` are in the allowed mime map in `wp-includes/functions.php`, and both image editors handle them.

`WP_Image_Editor_GD` has explicit branches for `image/avif` gated on `function_exists( 'imagecreatefromavif' )`, and `WP_Image_Editor_Imagick` has its own. Whether AVIF works on your host is a question about your PHP build, not about WordPress.

**It can read their dimensions without PHP support.** `wp_getimagesize()` falls back to parsing the file headers itself when the PHP build cannot: there is a `wp_get_avif_info()` helper in core that pulls width and height straight out of the AVIF container.

That fallback is what lets an AVIF upload still get correct `width` and `height` attributes on the front end, which matters more than it sounds, because [core refuses to make any loading or priority decision on an image with no dimensions](https://adityaarsharma.com/wordpress-lazy-loading-what-core-does/).

**It sets different default quality per format.** This one is buried in `WP_Image_Editor::get_default_quality()` and almost nobody knows it. The switch has one case, `image/webp`, which returns 86. Everything else falls through to `$this->default_quality`, which is 82.

Those are the numbers a WordPress site will actually encode at, so those are the numbers I measured with.

## The storage multiplication, counted on a real upload

Before comparing formats it is worth being precise about how many files one upload becomes, because the conversion decision multiplies against this number.

A stock install registers six sizes. Four come from options set in `wp-admin/includes/schema.php`:

| Size | Width | Height |
| ---- | ----- | ------ |
| thumbnail | 150 | 150 |
| medium | 300 | 300 |
| medium_large | 768 | 0 |
| large | 1024 | 1024 |

Two more are added in code by `_wp_add_additional_image_sizes()`, present since 5.3.0: `1536x1536` and `2048x2048`, described in the source as 2x medium_large and 2x large.

Sizes larger than the original are skipped, which you can verify from outside with `curl -o /dev/null -w "%{http_code} %{size_download}"` against each size. My own avatar is a 1000 by 1000 upload, so only the three smaller sizes exist:

| File | Status | Bytes |
| ---- | ------ | ----- |
| `Aditya-Sharma.jpg` | 200 | 108,189 |
| `Aditya-Sharma-150x150.jpg` | 200 | 2,887 |
| `Aditya-Sharma-300x300.jpg` | 200 | 8,143 |
| `Aditya-Sharma-768x768.jpg` | 200 | 47,493 |
Fetched from adityaarsharma.com on 3 September 2026, two seconds apart.
Four files, 166,712 bytes, from one upload. On a 3000 pixel wide photograph all six sizes generate, plus core's own scaled copy:

`big_image_size_threshold` defaults to 2560, and anything wider gets a `-scaled` version created and served as the full size while the true original is kept alongside.

That is eight files for one upload before a single theme size is registered, and a theme with four custom crops takes it to twelve.

### Why the multiplication decides your strategy

The multiplication is the part that decides your conversion strategy. Generating both a modern format and a fallback for every registered size doubles that number.

The Modern Image Formats plugin makes exactly this call, and it makes it the right way round, which I will come back to.

## Honest byte comparisons, measured on real files

Every WebP-versus-AVIF article quotes a percentage from somebody's benchmark.

I converted two of my own files at the exact quality settings WordPress core would have used, with the encoders on my laptop, and got a result that contradicts the received wisdom on one of them.

The tools, versioned: `cwebp` 1.6.0 with libsharpyuv 0.4.2, and `avifenc` 1.4.1 with dav1d 1.5.3 and aom 3.13.3.

### File one: a photograph

The 1000 by 1000 JPEG above, 108,189 bytes, exported from Photoshop:

| File | Bytes | Against the source |
| ---- | ----- | ------------------ |
| `hero.jpg` | 108,189 | source |
| `hero-q86.webp` | 72,920 | -32.6% |
| `hero-q82.avif` | 90,528 | -16.3% |
Encoded with `cwebp -q 86` and `avifenc -q 82 --speed 6`, the qualities core would use.
AVIF produced a file 24% larger than WebP on the same source at WordPress's own default quality settings. If your mental model is that AVIF is always smaller, that result should bother you. Mine did.

### File two: a screenshot

A 2800 by 3000 PNG, a full-page screenshot of the Query Monitor listing on wordpress.org. Flat colour, sharp text, one photographic banner in the middle. 1,122,260 bytes:

| File | Bytes | Against the source |
| ---- | ----- | ------------------ |
| `graphic.png` | 1,122,260 | source |
| `graphic-q86.webp` | 332,514 | -70.4% |
| `graphic-q82.avif` | 210,410 | -81.3% |
Same two encoders and quality numbers as the photograph.
Here AVIF wins, and wins clearly: 37% smaller than the WebP of the same image. Same two encoders, same two quality numbers, opposite conclusion.

![Bar chart: hero.jpg at 108,189 bytes, the WebP at 72,920 and the AVIF at 90,528.](https://adityaarsharma.com/wp-content/uploads/2026/09/aacf83ac-5103-4525-9558-c714047cbae2_2912x1632-scaled.png)Built from the byte counts measured in this post on 3 September 2026.

## Why the two files disagree, which is the part worth keeping

Three mechanisms, and none of them is a benchmark result you have to take on trust.

### The quality scales are not the same scale

`cwebp -q 86` and `avifenc -q 82` are two encoders' internal knobs.

They are not calibrated against each other, and neither is calibrated against JPEG's quality number. WordPress core treats them as interchangeable because a single integer is what its API exposes.

A fair comparison would fix a perceptual quality target such as SSIM or Butteraugli and find the bitrate each encoder needs to hit it.

I did not do that here, and any post that quotes a single AVIF-versus-WebP percentage without saying how it equalised quality is quoting a number that means nothing.

I am telling you what WordPress will actually produce with its own defaults, which is a different and more useful question than which codec is better.

### The photograph was already lossy

hero.jpg is a JPEG that has already been through a DCT quantiser. Re-encoding it stores the artifacts as if they were image detail, and high-quality settings preserve them faithfully and expensively.

This is exactly what WordPress does when a plugin converts an uploaded JPEG, so the number is representative rather than a mistake, but it does mean the comparison is between two re-encodes and not between two encodes of an original.

### AVIF's advantages are structural

They suit graphics. AVIF inherits AV1's intra-prediction modes and its much larger coding block sizes. Flat regions and hard edges, which is what a screenshot is made of, compress extremely well under that model.

Photographic noise does not, and that is where the cheaper, older WebP model stops losing. This is why the two files disagree and why a single blanket percentage cannot be right for both.

![Bar chart: graphic.png at 1,122,260 bytes, the WebP at 332,514 and the AVIF at 210,410.](https://adityaarsharma.com/wp-content/uploads/2026/09/4e889775-6ca6-4db7-afc0-6ecca7d1b7d1_2912x1632-scaled.png)Built from the byte counts measured in this post on 3 September 2026.

Newsletter

## Agents in Production

I check the things our industry takes on trust and publish what I actually found, including when it makes my own work look worse. One researched piece a week.

Email address

Get it weekly

Free. One email a week. Unsubscribe in one click, and I do not send anything else.

## The cost nobody puts in the comparison: encode time

Timed with `/usr/bin/time -p` on the same 2800 by 3000 image: `cwebp` took 0.39 seconds real, `avifenc --speed 6` took 0.86.

Roughly twice as long on a 2800 by 3000 image, on an idle laptop, at `--speed 6`. Lower the speed number for better compression and it gets slower fast.

Now multiply that by six registered sizes, and by two if you also generate fallbacks, and run it inside a PHP upload request on shared hosting with a 30 second execution limit.

That is the mechanism behind the upload timeouts people report after turning on modern format generation, and it is why the honest answer for a large existing library is to regenerate in the background with WP-CLI rather than at upload time.

## The plugin that actually does the conversion

The WordPress Performance Team ships it. It is called Modern Image Formats, its slug is still `webp-uploads` from when it was called WebP Uploads, and I pulled its numbers from `api.wordpress.org/plugins/info/1.2/` rather than the listing page.

Version 2.7.1, 100,000 active installs, tested against 7.1, last updated 26 August 2026. Its own description page states the policy plainly:

AVIF is generated if the hosting server supports it, otherwise WebP, and the choice is exposed under Settings then Media when both are available.

### Two behaviours people get caught by

First, only new uploads are converted; existing images stay as they are until you regenerate them, with `wp media regenerate` or a plugin.

Second, and this is the good design decision, by default only the *sub-sizes* become modern format. The originally uploaded file stays a JPEG or PNG.

There is an *Output fallback images* checkbox that generates both formats for every sub-size, and turning it on is what doubles your storage.

That default is the right way round. The original is your archive copy and the thing you regenerate from, so it should stay in the format with the widest possible tool support.

The sub-sizes are disposable derivatives, so they should be in whatever format is smallest today.

![The Modern Image Formats plugin listing on WordPress.org, slug webp-uploads.](https://adityaarsharma.com/wp-content/uploads/2026/09/0570019d-6131-442e-81d2-eb52c8093468_2800x2000-scaled.png)wordpress.org/plugins/webp-uploads/, screenshot taken 3 September 2026.

## Doing it yourself with the filter, and when not to

If you want the behaviour without the plugin, the filter is one callback. Hook `image_editor_output_format`, then set `$formats['image/jpeg']` and `$formats['image/png']` to `'image/webp'`.

Return the array core gave you with your entries added, rather than a fresh one. Replacing it wholesale drops the HEIC and HEIF mappings, and then an iPhone photo uploaded through the media library stops being converted to something browsers can display.

### Three reasons not to do it by hand

First, core's REST attachment controller deliberately disables the filter in places, with `add_filter( 'image_editor_output_format', '__return_empty_array', 100 )` around image editing operations, so that editing an image does not silently change its format; you would need to reproduce that care.

Second, your host may support WebP in GD but not AVIF, and you get to find out in production. Third, there is no fallback generation, so a visitor on a browser without WebP support gets nothing.

The plugin handles all three. Use the filter when you want to understand the mechanism, use the plugin when you want it to work.

## What does not work

**Converting everything to AVIF because a chart said it is smallest.** My photograph got 24% larger than the WebP. Convert a sample of your own library and count bytes before committing.

**Generating both formats for every size, everywhere.** That is six sizes times two formats plus two originals for one upload.

If your library is 20 gigabytes you now need 40, and your backups take twice as long. Turn on fallbacks only if your analytics show browsers that need them.

**Converting at upload time on shared hosting.** The encode-time numbers above are from a laptop with nothing else running. Do the initial pass with WP-CLI over SSH.

**Assuming a smaller file is a faster page.** On my own homepage the heaviest asset by a wide margin is a third-party JavaScript file, not an image, which is what [measuring the whole asset list](https://adityaarsharma.com/what-actually-makes-a-wordpress-site-slow/) showed.

Image format work is worth doing and it is rarely the largest number on the page.

[The Core Web Vitals piece](https://adityaarsharma.com/core-web-vitals-wordpress-2026/) has the framing for deciding which number to chase first, and [the bulk compression walkthrough](https://adityaarsharma.com/how-to-compress-wordpress-images-in-bulk/) covers the pass you should run before any of this.

## One thing to do next

Take the largest image in your uploads directory and convert it twice, at the exact qualities core would use:

`cwebp -q 86 -quiet yourfile.jpg -o out.webp
avifenc -q 82 --speed 6 yourfile.jpg out.avif
ls -l yourfile.jpg out.webp out.avif`
If AVIF is smaller, your library is probably graphics and screenshots and you should prefer AVIF.

If WebP is smaller, your library is photographs and you should prefer WebP. Repeat on four or five files before you set a site-wide policy, because one file is an anecdote.

If you need to sweep a lot of attachments once you have decided, [the bulk editing over the REST API post](https://adityaarsharma.com/bulk-edit-wordpress-rest-api/) covers doing that without breaking things.

## Resources

- [Modern Image Formats on wordpress.org](https://wordpress.org/plugins/webp-uploads/), the Performance Team plugin. Version 2.7.1, 100,000+ installs, updated 26 August 2026.- [image_editor_output_format](https://developer.wordpress.org/reference/hooks/image_editor_output_format/), the one filter that changes conversion policy.- [wp media regenerate](https://developer.wordpress.org/cli/commands/media/regenerate/), for converting an existing library outside a web request.- [cwebp command line reference](https://developers.google.com/speed/webp/docs/cwebp), from the libwebp project.- [libavif on GitHub](https://github.com/AOMediaCodec/libavif), which ships the avifenc binary used above.- [caniuse: AVIF support](https://caniuse.com/avif), for deciding whether you still need fallback images.