This almost drove me crazy! Seriously. I checked everything, every extension, config and yet I'm getting the wrong images because I missed this tiny detail!
Images are usually the heaviest things on a web page. A single photo can be bigger than all the code on the page combined.
WebP is a newer image format from Google that makes images smaller - sometimes 30% smaller - without looking any different to the human eye. Smaller images mean faster pages. Faster pages mean happier visitors.
In this post I'll show you how I set up TYPO3 to automatically serve WebP images to browsers that support them - without touching any templates or HTML.
The Problem With Just Uploading a WebP File
The obvious answer sounds simple: just upload WebP files instead of PNG or JPG. But it doesn't work that cleanly. TYPO3 stores image references in the database by filename. Change the file, break the reference. And older browsers still don't support WebP - they'll show a broken image instead (shouldn't be a problem these days but you never know).
What we really want is to keep the PNG or JPG as the source of truth, but serve WebP to browsers smart enough to handle it. Silently. Automatically.
The best performance optimization is the one your users never notice. They just experience a faster website.
Step 1 - Let TYPO3 Generate the WebP Files
The plan2net/webp extension hooks into TYPO3's image processing pipeline. Every time TYPO3 resizes or crops an image, the extension runs the result through GraphicsMagick and creates a .webp copy right next to the original processed file.
So when TYPO3 creates this processed file:
csm_Typo3dockergitlab_6ce5166ccb.png
The extension automatically creates this alongside it:
csm_Typo3dockergitlab_6ce5166ccb.png.webp
You can verify this yourself on the server:
find ~/pages/typo3blogs/data/fileadmin/_processed_ -name "*.webp" | head -10
If you see .webp files sitting next to .png files - the first step is done.

Step 2 - Tell Apache to Serve WebP Automatically
The WebP files exist on disk. But Apache doesn't know to use them yet. The HTML still says src="image.png" and Apache obediently serves the PNG.
We fix this with a simple rewrite rule in the Apache virtual host config. It says, If the browser supports WebP, and a .webp version of the requested file exists, serve that instead.
AddType image/webp .webp
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule ^(.+\.(jpe?g|png))$ $1.webp [T=image/webp,E=ACCEPT_WEBP:1,L]
Header append Vary Accept env=ACCEPT_WEBP
Let's break that down line by line:
- RewriteCond %{HTTP_ACCEPT} image/webp - only rewrite if the browser said it can handle WebP
- RewriteCond %{REQUEST_FILENAME}.webp -f - only rewrite if a
.webpfile actually exists on disk - RewriteRule ... - serve the
.webpfile, tell the browser its content type isimage/webp - Header append Vary Accept - tell caches to store PNG and WebP versions separately
The HTML never changes. The image src still says .png. The browser asks for a PNG - Apache quietly hands it a WebP. That's it.
Why the Vary Header Matters
Without the Vary: Accept header, a caching layer like Varnish might cache the WebP version and then serve it to a browser that doesn't support WebP - breaking the image. The Vary header tells every cache in the chain: "this response depends on what the browser said it accepts, so store them separately."
How to Check If It's Working
So this is the part that drove me crazy! You don't see any changes on the website or inside the html code. There is still the original .png/.jpeg/.whateverfile referenced.
So what you need to do is check the content type that actually has been served.
curl -sI -H "Accept: image/webp,*/*" felix-dziekan.de | grep -i "content-type\|vary"
You should see:
content-type: image/webp
vary: Accept
Or open your browser's DevTools, go to the Network tab, reload the page, and click any image. The Content-Type should say image/webp even though the src in the HTML still says .png.

The Result
Every visitor using a modern browser - which is basically everyone - now gets WebP images automatically. No template changes. No database changes. No broken images for anyone on an old browser. The PNG files stay exactly where they are as a fallback.
Two config files, a handful of lines, and your images are measurably faster.