LAUNCH DEAL — LIMITED Das Nest Lifetime 499 € 149 € Get the deal →
KakapoWP KakapoWP
Help Center/Performance/Set up WebP and AVIF

Set up WebP and AVIF

Applies to: Kakapo Performance· 6 min read

First check what your server can do

In the “Images” area you find the card “Capabilities of this server”. It shows not what is on paper, but what was measured on the running PHP: the GD image library including its version, reading JPEG, reading PNG, reading WebP, writing WebP, writing AVIF. The check asks twice — the function must exist and the format must appear in imagetypes(). That matters, because some hosts build GD without WebP or AVIF: imagewebp() is then present and only fails when called.

If a format is missing, the switch that belongs to it does stay visible, but it is disabled and carries the reason. For WebP it reads: GD must be built with libwebp. For AVIF: PHP 8.1 or newer with libavif. Both are a matter for your host. A detour via the AJAX call does not help — the server explicitly refuses to switch on a format that is not available.

The line “Imagick” is purely informational. This module does not use Imagick; if it says “not available” there, you are not missing anything.

Switching on and setting the three numbers

There are three switches and three number fields. “Generate WebP” and “Generate AVIF” are off out of the box, “Deliver via <picture>” is on. The separation is intentional: you can first let the files come into being and switch delivery on later. Conversely: if you switch delivery off, the files are still created, but visitors get unchanged markup.

WebP quality is set to 82, AVIF quality to 50. Both fields accept values from 30 to 100; anything above or below that is trimmed to the range. The different defaults are no oversight: AVIF measures differently than JPEG, and 50 already looks very clean there. Above 90 the file grows faster with WebP than the visible gain.

The upper limit in megapixels is set to 40 and accepts values from 4 to 400. It protects against the memory limit: a 6000 × 4000 photo occupies around 96 MB while being decoded, regardless of how large its file is. In addition, before every decode Kakapo calculates against the memory actually still free and skips, instead of letting the upload die at the limit.

If you change one of the three switches, the stored page cache is discarded. Quality and the megapixel limit leave it in place — they only take effect on the next upload and do not make any already stored page wrong.

What happens during the upload

The conversion runs at the end of the upload, as soon as WordPress has generated all image sizes. What gets processed is the file from the metadata and every generated size — not the original kept by the core, which is never delivered anyway.

Every derivative sits as a companion file next to its source file and carries its full name plus the extension: bild.jpg becomes bild.jpg.webp, not bild.webp. The reason: bild.jpg and bild.png are allowed to sit next to each other in the same folder; if the extension were merely replaced, one derivative would overwrite the other. If something is already at the target location, it is not touched.

Writing goes first into a secondary file with the process number and a random value in its name. Only when it measures smaller than the source file does it move into its place via rename. If it is larger or the same size, it is deleted and the source file stays. An aborted run therefore never leaves an oversized derivative behind.

The upload has a time budget of 12 seconds. AVIF is many times slower to generate than WebP, and six sizes times two formats would otherwise run into the web server's execution time — the site owner would see an aborted upload. Whatever no longer fits is picked up by a one-off follow-up run: it is scheduled 30 seconds later and then has 90 seconds. What has been done, as well as what has been skipped, is recorded on the attachment, so that the same attempt is not repeated on every regeneration.

With JPEGs an EXIF rotation is carried over, because WebP and AVIF from GD do not carry this information along. With PNG source files Kakapo tries WebP losslessly first — logos, graphics and screenshots often become smaller that way, without edges fraying. Transparency is preserved in both target formats.

How delivery works

Kakapo wraps the <img> in a <picture> and places AVIF and WebP sources in front of it, AVIF first — the browser takes the first source it understands. The <picture> gets display:contents, so that it does not push an additional box into the arrangement in the flex and grid layouts of your theme.

Deliberately chosen over the alternative via .htaccess: content negotiation needs Apache rules, has no effect at all on nginx and collides with CDN caches that do not vary the Accept header. With <picture> the browser decides, without a single line of server configuration.

Post content and featured images are hooked, with priority 22 — after lazy-load (20), before the CDN rewrite (25), so that the newly created sources also run via the CDN. Existing <picture> blocks remain untouched, as do images from other hosts and everything outside the uploads folder.

One rule is worth knowing: a format is only offered if the largest version in the srcset exists as a derivative. If a medium or small one is missing, the browser reaches for the next larger one — a few kilobytes more, but never a blurry image. If the largest one were missing, a wide screen could no longer reach the full resolution; that is precisely the case being ruled out.

When nothing is created: reading the reasons

The card “Generated files & real savings” shows, for each format, the number of files, the total of the source files, the total of the derivatives and the difference. Every number comes from the comparison of two actual file sizes at the moment of creation — nothing is estimated or extrapolated. “Source files” is only the total of the files for which a derivative was created, not your entire media library.

Below that you see what was not converted, with a reason. The most important ones:

“Result was larger than the source file” — not an error. With very small thumbnails this happens regularly with AVIF; the source file stays and the remaining sizes get their derivative all the same.

“Not writable” — check the permissions in the uploads folder. That is the only reason that really calls for you.

“A file was already at the target location” — it was not overwritten. Usually it comes from the batch run over your existing files and is already exactly what was supposed to be created here.

“Did not fit into memory” — raise the megapixel limit or the PHP memory limit.

“Not readable” — a corrupt file, a CMYK JPEG or an exotic variant. “Not JPEG/PNG/WebP” — GIF animations and PDFs are deliberately left untouched.

If the card stays empty, switch WebP on and upload an image. Images that are already in the media library are not reached that way, but via the batch run further down on the same page.

Was this article helpful?