PHPackages                             plan2net/webp - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. plan2net/webp

ActiveTypo3-cms-extension[Image &amp; Media](/categories/media)

plan2net/webp
=============

Drop-in WebP, AVIF, and JPEG XL delivery for TYPO3 images — automatic, no URL or template changes

14.7.0(2w ago)681.5M↓46.3%402GPL-3.0-or-laterPHPPHP &gt;=8.2CI passing

Since Mar 14Pushed 3w ago6 watchersCompare

[ Source](https://github.com/plan2net/webp)[ Packagist](https://packagist.org/packages/plan2net/webp)[ Docs](https://www.plan2.net/)[ RSS](/packages/plan2net-webp/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (25)Versions (51)Used By (2)

WebP / AVIF / JPEG XL for TYPO3 CMS
===================================

[](#webp--avif--jpeg-xl-for-typo3-cms)

[![Packagist Version](https://camo.githubusercontent.com/bdb38606799211937eb4e62a1855bf6607736917183b9a55cee7ff16adbf958d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f706c616e326e65742f776562702e737667)](https://packagist.org/packages/plan2net/webp)[![Downloads](https://camo.githubusercontent.com/13eb25af9259efee157c914a7f108fc110528040cf9ee9d63afd69067235f7ba/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f706c616e326e65742f776562702e737667)](https://packagist.org/packages/plan2net/webp)[![Tests](https://github.com/plan2net/webp/actions/workflows/tests.yml/badge.svg)](https://github.com/plan2net/webp/actions/workflows/tests.yml)[![Supported TYPO3](https://camo.githubusercontent.com/b8f522ba572234c51ccfd790b9ed63c81c33e6f88c6dbfb24b42eea046a75ed5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31322e3425323025374325323031332e3425323025374325323031342d6f72616e67652e737667)](https://get.typo3.org/)[![Supported PHP](https://camo.githubusercontent.com/ccafaac08e907346e18f4101146b0001c66cdcda9d7392798783bdccbe4f6f01/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f706c616e326e65742f776562702e737667)](https://packagist.org/packages/plan2net/webp)[![License](https://camo.githubusercontent.com/8b59d97f09166dc0016167b7b0cf9a5830ee03c63f582ebd7ed5848ad497f1ef/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d47504c2d2d332e302d626c75652e737667)](LICENSE)

Serve modern image formats — **WebP, AVIF, JPEG XL** — to browsers that support them, **without changing your URLs or HTML**. The extension creates sibling files (`photo.jpg.webp`, `photo.jpg.avif`, `photo.jpg.jxl`) next to every processed image; your webserver picks the best match per request via `Accept`-header content negotiation. Browsers that don't accept any of the modern formats receive the original JPEG/PNG/GIF.

Pick any combination of formats via the [`formats_enabled`](#formats_enabled) setting. WebP is active by default.

Note

The Composer package is still `plan2net/webp` and the TYPO3 extension key is still `webp` — names kept for backwards compatibility with 1.5M+ existing installs. The runtime supports all three formats regardless.

See [CHANGELOG.md](CHANGELOG.md) for release notes.

Contents
--------

[](#contents)

- [Compatibility](#compatibility)
- [Requirements](#requirements)
- [Installation](#installation)
- [Updating](#updating)
- [Configuration](#configuration)
- [Per-image compression](#per-image-compression)
- [Compress larger variants harder](#compress-larger-variants-harder)
- [Async mode](#async-mode)
- [Webserver configuration](#webserver-configuration)
- [Remote storages (S3, Azure, custom FAL drivers)](#remote-storages-s3-azure-custom-fal-drivers)
- [Verifying it works](#verifying-it-works)
- [Diagnosing your installation](#diagnosing-your-installation)
- [Troubleshooting](#troubleshooting)
- [Known limitations](#known-limitations)

When to use this vs. TYPO3 core image conversion
------------------------------------------------

[](#when-to-use-this-vs-typo3-core-image-conversion)

TYPO3 core can already produce modern formats — this extension solves a different problem. The distinction is the delivery model, not the format list:

- **WebP** is a processing format since TYPO3 v13.0.
- **AVIF** is a processing format since TYPO3 v13.4, but only via **ImageMagick** and **not by default** — GraphicsMagick has no AVIF support, so core only enables it when ImageMagick reports the capability (or you add `avif` to `imagefile_ext` yourself).
- TYPO3 **v14** added `$GLOBALS['TYPO3_CONF_VARS']['GFX']['imageFileConversionFormats']`, an input→output format map (e.g. `'jpg' => 'webp'`, `'default' => 'avif'`).

In every core variant the processed file's extension — and therefore its URL — changes (`photo.jpg` → `photo.webp` / `photo.avif`). This extension instead writes sibling files next to the original and serves them via webserver content negotiation, so the URL never changes.

ConcernThis extensionTYPO3 coreFormats supportedWebP, AVIF, JPEG XLWebP (13.0+), AVIF (13.4+, ImageMagick) — **no JPEG XL**URL of served imageUnchanged (`photo.jpg`)Changed (`photo.webp` / `photo.avif`)HTML / templatesUnchangedReference new URLFallback for browsers that lack the served formatTransparent via webserverNeed `` or polyfillRequires webserver rewrite ruleYesNoWorks with cached HTML / CDN URLsYesCache invalidation neededUse the core mechanism if you can change URLs. Use this extension if URLs must stay stable (cached HTML, CDN, stable references), you want transparent per-request fallback, or you want **JPEG XL**.

About the formats
-----------------

[](#about-the-formats)

FormatReleasedCoverage (May 2026)¹Typical size²Notes**WebP**2010~95.6%−25 to −34% vs JPEG; −26% vs PNGMature; broadest browser support**AVIF**2019~94%~−20 to −30% vs WebP at equal SSIMAV1-based; supported by Chrome 85+, Firefox 93+, Safari 16+**JPEG XL**2022~17%Comparable to AVIF, often better at losslessSupported by Safari 17+; coverage growing- ¹ caniuse.com, StatCounter data, April 2026.
- ² Per Google reference numbers and AVIF benchmark suites; real-world savings vary with content.

All three support lossy and lossless modes, transparency, and ICC color profiles. WebP and the libvips path also support animation; AVIF and JPEG XL animation depend on the chosen converter.

Smaller image payloads improve Core Web Vitals directly. Largest Contentful Paint (LCP) benefits most: image bytes shrink while rendered dimensions stay the same. A 25–34% bandwidth reduction adds up on image-heavy pages and mobile connections.

### Converter × format support matrix

[](#converter--format-support-matrix)

Pick a converter per format that matches what's actually installed on the host. The four built-in converters cover the cross-product like this:

Converterwebpavifjxl`VipsConverter`✓✓¹✓²`MagickConverter`✓✓³✓⁴`ExternalConverter`✓✓⁵✓⁶`PhpGdConverter`✓✗✗- ¹ libvips built with libheif (AV1 encoder)
- ² libvips built with libjxl
- ³ ImageMagick with libheif AV1 delegate
- ⁴ ImageMagick 7+ with libjxl delegate
- ⁵ command-defined, e.g. `avifenc`
- ⁶ command-defined, e.g. `cjxl`

`webp:diagnose` verifies per-format delegate availability — see [Diagnosing your installation](#diagnosing-your-installation).

Compatibility
-------------

[](#compatibility)

Extension versionTYPO3PHPStatus14.x12.4, 13.4, 14.x8.2, 8.3, 8.4Current13.x13.48.2, 8.3Legacy5.x12.48.1, 8.2LegacyRequirements
------------

[](#requirements)

You need an image converter on the host that can write the output formats you enable. The extension ships four converter backends — pick whichever fits your stack from the matrix above.

For the WebP-only default install:

- **ImageMagick** or **GraphicsMagick** compiled with WebP delegate, **or**
- **PHP GD** with the `IMG_WEBP` flag at runtime, **or**
- **libvips** in-process via [`jcupitt/vips`](https://packagist.org/packages/jcupitt/vips) + PHP `ext-ffi`, **or**
- Any other external WebP encoder such as [`cwebp`](https://developers.google.com/speed/webp/docs/cwebp).

For **AVIF** and **JPEG XL** you additionally need:

- **libvips** built with libheif (AVIF) and/or libjxl (JPEG XL) — the simplest path; one `apt install libvips-tools libheif1 libjxl-tools` covers both, plus `composer require jcupitt/vips`.
- **OR ImageMagick** with the matching delegates (`libheif` with the AV1 encoder for AVIF, `libjxl` for JPEG XL).
- **OR external encoders** like `avifenc` (libavif) and `cjxl` (libjxl) wired through `ExternalConverter`.

Verify your existing setup:

```
# GraphicsMagick — should return "yes" for any format you've enabled
gm version | grep -iE "webp|heif|jxl"

# ImageMagick — listed AVIF / JXL should be flagged "rw" (read+write)
convert -list format | grep -iE "WEBP|AVIF|JXL"
```

`webp:diagnose` runs the equivalent checks for the currently-configured converter per format — see [Diagnosing your installation](#diagnosing-your-installation).

Installation
------------

[](#installation)

```
composer require plan2net/webp
```

Then:

1. Activate the extension if your TYPO3 is in non-Composer mode (Composer mode activates it automatically).
2. Flush TYPO3 and PHP caches.
3. Clear processed files (*System → Maintenance → Remove Temporary Assets* on TYPO3 v14; *Admin Tools → Maintenance* on v12/v13).
4. Add the [webserver rewrite rules](#webserver-configuration).

Updating
--------

[](#updating)

After a `composer update`, **save the extension settings at least once** via the Extension Configuration backend module (*System → Settings → Extension Configuration → webp* on TYPO3 v14; *Admin Tools → Settings → Extension Configuration → webp* on v12/v13). TYPO3 only writes default values to `LocalConfiguration` when you save the settings form, so any new defaults the upgraded version ships won't take effect until you do.

### Upgrading to multi-format output

[](#upgrading-to-multi-format-output)

Existing installs keep generating WebP only because `formats_enabled` defaults to `webp`. To enable AVIF or JPEG XL:

1. Run the TYPO3 database analyzer once — `tx_webp_queue` and `tx_webp_failed` gain a `format` column with default `'webp'`, so existing rows remain valid without a data migration.
2. Open the AVIF (or JXL) tab in the Extension Configuration, fill in `converter_avif` + `parameters_avif` + `mime_types_avif`, and add the format name to `formats_enabled` (e.g. `webp,avif`).
3. Update the webserver rewrite rules to serve the new sibling — see [Webserver configuration](#webserver-configuration). Without that update, AVIF/JXL siblings sit on disk unused.

3rd-party custom converters that implement only `Plan2net\Webp\Converter\Converter` continue to work for the WebP slot. To opt them into AVIF or JXL, implement `Plan2net\Webp\Converter\MultiFormatConverter` (a separate interface that takes the format as a 3rd argument) — or extend `Plan2net\Webp\Converter\AbstractConverter`, which now provides both.

Configuration
-------------

[](#configuration)

[![Extension settings](Documentation/extension_settings.png)](Documentation/extension_settings.png)

SettingDefaultPurpose[`async`](#async)`0`Queue conversions for a scheduler worker instead of running them on the page-render path[`async_throttle_ms`](#async_throttle_ms)`0`Random per-conversion sleep (ms) in the worker; 0 disables[`convert_all`](#convert_all)`1`Convert all images, not just `_processed_`[`exclude_directories`](#exclude_directories)*(empty)*Skip processing for matching paths[`filter_pattern`](#filter_pattern)`/\.(jpe?g|png|gif)\.(webp|avif|jxl)$/i`PCRE for which siblings to hide (only when `hide_webp`)[`formats_enabled`](#formats_enabled)`webp`Output formats to generate, comma list of `webp,avif,jxl`[`hide_webp`](#hide_webp)`1`Hide generated sibling files (`.webp` / `.avif` / `.jxl`) in the BE file list[`mime_types`](#mime_types)`image/jpeg,image/png,image/gif`Source mime types convertible to `webp`[`parameters`](#parameters)See belowPer-mime-type WebP converter parameters (the `webp` slot)[`parameters_avif`](#parameters_avif)See belowPer-mime-type AVIF converter parameters[`parameters_jxl`](#parameters_jxl)See belowPer-mime-type JPEG XL converter parameters[`silent`](#silent)`1`Suppress converter stdout/stderr (Linux only)[`use_system_settings`](#use_system_settings)`1`Reuse GFX color profile settings (MagickConverter)Each non-webp format adds its own `converter_`, `parameters_`, and `mime_types_` settings in dedicated `cat=avif` / `cat=jxl` tabs of the Extension Configuration form. See [`formats_enabled`](#formats_enabled) and the per-format `parameters_avif` / `parameters_jxl` sections below.

### `async`

[](#async)

```
# cat=async; type=boolean; label=Enable asynchronous conversion
async = 0

```

When enabled, the `AfterFileProcessing` listener writes a row to `tx_webp_queue` instead of running the converter inside the request. Conversions then happen out-of-band via the `webp:process-queue` CLI command, typically registered as a TYPO3 Scheduler task. See [Async mode](#async-mode) below for setup.

When disabled (default), conversions run synchronously exactly as before.

### `async_throttle_ms`

[](#async_throttle_ms)

```
# cat=async; type=int+; label=Random sleep (ms) between conversions
async_throttle_ms = 0

```

Pause for a random interval between conversions inside the worker. Value `0` means no pause. Value `N > 0` means each pause is `random(N/2, N*3/2)` milliseconds, so a batch of conversions doesn't saturate CPU in lock-step. Applies to both queue mode and `--folder` mode.

### `convert_all`

[](#convert_all)

```
# cat=basic; type=boolean; label=Convert all images in local and writable storage and save a copy in Webp format; disable to convert images in the _processed_ folder only
convert_all = 1

```

When enabled (default), every image in every local + writable storage gets siblings (in every enabled format) — not just images that TYPO3 has actually processed into `_processed_/`. To revert to processing-only behaviour, disable the checkbox.

Source-folder siblings are kept in sync with TYPO3's FAL operations: moving an image moves all its siblings (`.webp`/`.avif`/`.jxl`), deleting removes them, replacing drops the stale set so the next render produces fresh ones. When a storage has a recycler, the siblings follow the file into the recycler so restore keeps the set intact. No configuration needed.

### `exclude_directories`

[](#exclude_directories)

```
# cat=basic; type=string; label=Exclude processing of images from specific directories (separated by semicolon)
exclude_directories =

```

Skip processing for images under any of the listed paths (semicolon-separated).

Example: `/fileadmin/demo/special;/another-storage/demo/exclusive`

### `filter_pattern`

[](#filter_pattern)

```
# cat=basic; type=string; label=Pattern to filter out files
filter_pattern = /\.(jpe?g|png|gif)\.(webp|avif|jxl)$/i

```

PCRE pattern matched against the file identifier when [`hide_webp`](#hide_webp) is enabled. The default matches the sibling-file naming this extension produces (`photo.jpg.webp`, `photo.jpg.avif`, `photo.jpg.jxl`) without hiding standalone `.webp` / `.avif` / `.jxl` files. Override if you use a custom naming scheme.

Invalid patterns are silently ignored (no files are hidden, no errors raised).

### `formats_enabled`

[](#formats_enabled)

```
# cat=basic; type=string; label=Output formats to generate (comma-separated list of webp,avif,jxl)
formats_enabled = webp

```

Comma-separated list of output formats this install should produce. Each enabled format generates its own sibling next to the original (and its own row in `sys_file_processedfile`). Set to `webp,avif` to ship both kinds of siblings, `avif,jxl,webp` to ship all three.

Each non-webp format reads its converter and parameters from per-format keys (in their own `cat=avif` / `cat=jxl` tabs in the Extension Configuration form):

- `converter_avif`, [`parameters_avif`](#parameters_avif), `mime_types_avif`
- `converter_jxl`, [`parameters_jxl`](#parameters_jxl), `mime_types_jxl`

The legacy `converter` + `parameters` + `mime_types` keys remain the source of truth for the WebP slot.

Both `parameters_avif` and `parameters_jxl` ship with ImageMagick-compatible defaults so enabling a format works out of the box on the typical TYPO3 host. Tune to your stack — recipes for libvips and external binaries are under [`parameters_avif`](#parameters_avif) and [`parameters_jxl`](#parameters_jxl) below.

### `hide_webp`

[](#hide_webp)

```
# cat=basic; type=boolean; label=Hide sibling files (.webp/.avif/.jxl) matching the filter pattern in backend file list module
hide_webp = 1

```

Hides generated sibling files (`.webp`, `.avif`, `.jxl`) in the backend file list module. The pattern controlling **which** files are hidden is [`filter_pattern`](#filter_pattern).

Note

The setting key is `hide_webp` for backwards compatibility with installs that wrote it before AVIF/JPEG XL existed; semantically it covers all sibling formats.

For a more customised behaviour (e.g. show siblings only to a specific BE group), override `$GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks']` in your own extension — see `ext_localconf.php` for the registration this extension performs.

### `mime_types`

[](#mime_types)

```
# cat=basic; type=string; label=Supported mime types (comma separated)
mime_types = image/jpeg,image/png,image/gif

```

Only source files whose mime type is in this comma-separated list are considered for conversion to the WebP slot. AVIF and JPEG XL have their own per-format `mime_types_avif` / `mime_types_jxl` lists.

### `parameters`

[](#parameters)

Each entry is `mime/type::params`, separated by `|`. The `::` is significant — a single colon doesn't match, and the value is then treated as default parameters for any mime type.

Default (ImageMagick/GraphicsMagick):

```
parameters = image/jpeg::-quality 85 -define webp:lossless=false|image/png::-quality 75 -define webp:lossless=true|image/gif::-quality 85 -define webp:lossless=true

```

Per-mime-type breakdown:

Mime typeDefault parameters`image/jpeg``-quality 85 -define webp:lossless=false``image/png``-quality 75 -define webp:lossless=true``image/gif``-quality 85 -define webp:lossless=true`Reference:

- [ImageMagick WebP options](https://www.imagemagick.org/script/webp.php)
- [GraphicsMagick options](http://www.graphicsmagick.org/GraphicsMagick.html)

Warning

Try raising `quality` before reaching for `webp:lossless=true`; lossless can produce files *larger* than the original.

#### Using an external binary

[](#using-an-external-binary)

Supply a command string with exactly two `%s` placeholders for the source and target file:

```
image/jpeg::/usr/bin/cwebp -jpeg_like %s -o %s|image/png::/usr/bin/cwebp -lossless %s -o %s|image/gif::/usr/bin/gif2webp %s -o %s

```

See [`cwebp` documentation](https://developers.google.com/speed/webp/docs/cwebp).

With libvips's `vips` CLI binary:

```
image/jpeg::/usr/bin/vips webpsave %s %s --Q 85 --effort 4 --smart-subsample|image/png::/usr/bin/vips webpsave %s %s --Q 75 --lossless --effort 4|image/gif::/usr/bin/vips webpsave %s[n=-1] %s --Q 75 --lossless --effort 4 --mixed

```

The GIF entry uses `%s[n=-1]` on the source so libvips reads all frames; without it only the first frame survives and `--mixed` (a save-side option) can't recover the rest. See the [libvips CLI reference](https://www.libvips.org/API/current/using-the-cli.html).

#### Using libvips natively

[](#using-libvips-natively)

Pick **libvips (native)** from the converter dropdown for the fastest path: 2–3× faster than MagickConverter at equivalent quality, substantially less memory, and animated GIFs survive as animated WebP automatically.

Install the libvips shared library, enable PHP's FFI extension, and require the PHP binding:

```
apt install libvips-tools           # Debian/Ubuntu — pulls in libvips42 / libvips42t64
brew install vips                   # macOS
composer require jcupitt/vips
```

Set `parameters` to:

```
image/jpeg::Q=85 smart_subsample=true effort=4|image/png::Q=75 lossless=true effort=4|image/gif::Q=75 lossless=true mixed=true effort=4

```

Options are passed straight to libvips's `webpsave` — see the [option reference](https://www.libvips.org/API/current/VipsForeignSave.html#vips-webpsave) for the full list.

Important

Set `ffi.enable=true` in php.ini (not `preload` — jcupitt/vips does not support FFI preloading). On PHP 8.3+ also set `zend.max_allowed_stack_size=-1`; without it the default stack limit can cause spurious conversion failures.

### `parameters_avif`

[](#parameters_avif)

Same `mime/type::params|…` syntax as [`parameters`](#parameters). Default targets ImageMagick (matches the default `converter_avif`):

```
parameters_avif = image/jpeg::-quality 60|image/png::-quality 75|image/gif::-quality 60

```

BackendRecommended `parameters_avif``MagickConverter``image/jpeg::-quality 60|image/png::-quality 75|image/gif::-quality 60``VipsConverter``image/jpeg::Q=60 effort=4|image/png::Q=60 effort=4|image/gif::Q=60 effort=4``ExternalConverter``image/jpeg::/usr/bin/avifenc --min 30 --max 50 %s %s|image/png::…|image/gif::…`AVIF at quality ~60 typically matches WebP at quality ~85 in filesize, often at better SSIM. For ImageMagick, `-quality` covers the common case; advanced encoders also accept `-define heic:speed=2` (slower, better compression) on builds with the libheif AV1 delegate.

References:

- [libheif AV1 encoder options](https://github.com/strukturag/libheif/blob/master/aom-options.md) (used by ImageMagick when compiled with libheif)
- [libvips `heifsave` reference](https://www.libvips.org/API/current/VipsForeignSave.html#vips-heifsave) (the libvips AVIF entry point)
- [`avifenc`](https://github.com/AOMediaCodec/libavif#installation) command-line flags

`webp:diagnose` reports per-mime-type parameter resolution; if you enable AVIF and leave entries missing, it tells you which lines to add.

### `parameters_jxl`

[](#parameters_jxl)

Same syntax. Default targets ImageMagick:

```
parameters_jxl = image/jpeg::-quality 75|image/png::-quality 90|image/gif::-quality 75

```

BackendRecommended `parameters_jxl``MagickConverter``image/jpeg::-quality 75|image/png::-quality 90|image/gif::-quality 75``VipsConverter``image/jpeg::Q=75 effort=7|image/png::lossless=true effort=7|image/gif::lossless=true effort=7``ExternalConverter``image/jpeg::/usr/bin/cjxl --quality 75 %s %s|image/png::/usr/bin/cjxl --lossless_jpeg=0 %s %s|…`JXL preserves PNG well in modular (lossless) mode — for `image/png`, prefer a higher quality value (or `lossless=true` on libvips) than for JPEG.

References:

- [libjxl encoder options](https://github.com/libjxl/libjxl/blob/main/doc/man/cjxl.txt)
- [libvips `jxlsave` reference](https://www.libvips.org/API/current/VipsForeignSave.html#vips-jxlsave)

### `silent`

[](#silent)

```
# cat=basic; type=boolean; label=Suppress output (stdout, stderr) from the external converter command
silent = 1

```

Suppress stdout/stderr from external converters. Linux only.

### `use_system_settings`

[](#use_system_settings)

```
# cat=basic; type=boolean; label=Use the system GFX "processor_stripColorProfileCommand"/"processor_stripColorProfileParameters" setting for the MagickConverter converter
use_system_settings = 1

```

Applies only to `MagickConverter`. When enabled, the value of `$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_stripColorProfileCommand']` and `processor_stripColorProfileParameters` is appended to converter arguments automatically — no need to repeat the setting per mime type.

`PhpGdConverter` and external-binary configurations ignore this flag.

Per-image compression
---------------------

[](#per-image-compression)

The [`parameters`](#parameters) quality is a site-wide default. For a single image that tolerates stronger compression — a full-bleed hero, say — edit its metadata in the **Filelist** and set **Compression quality** (`1`–`100`, lower = smaller file; `0` keeps the global setting); it applies to that file across every enabled format, overrides the `-quality` / `Q=` / `quality=` token, and is read at conversion time so changing it regenerates the sibling on the next render. Right below the field, a read-only report shows what was achieved — per processed variant and format, the generated sibling's size and the saving versus the source it replaces — filling in as the image is rendered at more sizes (a dash means the converter produced nothing smaller at the current quality).

[![Per-image compression quality and results in the file metadata form](Documentation/compression_report.png)](Documentation/compression_report.png)

Note

Already-rendered pages keep serving the previous sibling from cache until they are re-rendered. After changing an in-use image's quality, flush the affected frontend caches (or wait for them to expire) to see the new sibling.

Compress larger variants harder
-------------------------------

[](#compress-larger-variants-harder)

A responsive site renders the same image at many widths (`480`, `768`, `1200`, `1536`, …). A fixed quality over-pays on the large variants: at high pixel density the eye no longer resolves compression artifacts — they shrink to sub-pixel noise once the image is displayed or downscaled — so a large variant can be compressed far harder than a small one with no visible loss. Image CDNs already do this; imgix, for example, serves roughly quality **80 at 1×, 40 at 2×, 20 at 3×**. The biggest variants are also the most expensive to download, so this is where the bytes are.

This extension applies the same idea through a **width-to-quality curve** per output format. It ships **off by default** (no change to existing output on upgrade) — paste a curve into the Extension Configuration to switch it on.

### Recommended starting point — copy &amp; paste

[](#recommended-starting-point--copy--paste)

Paste these into *Settings → Extension Configuration → webp* (the `basic`, `avif`, and `jxl` tabs). They take effect for siblings generated from then on:

```
quality_by_width       = 640:80|768:74|1024:70|1536:64|2048:58
quality_by_width_avif  = 640:62|1024:54|1536:48|2048:44
quality_by_width_jxl   = 640:70|1024:62|1536:56|2048:50

```

These are a sensible **starting point — tune to your content**: photographic images take aggressive compression well, flat graphics and text show artifacts sooner. AVIF and JPEG XL reach the same perceived quality roughly 10–15 points below WebP, which is why their curves sit lower. Only configure the formats you have enabled in [`formats_enabled`](#formats_enabled); leave a setting empty to disable the curve for that format.

### How it works

[](#how-it-works)

Each setting is a list of `maxWidth:quality` bands separated by `|`. When webp generates a sibling it looks up the **rendered variant's width** and uses the quality of the smallest band whose `maxWidth` is greater than or equal to that width; a variant wider than the largest band takes the largest band's quality. The resolved value replaces the `-quality` / `Q=` / `quality=` token in that format's [`parameters`](#parameters).

Worked example for `quality_by_width = 640:80|1024:72|1536:64`:

Variant widthBand usedQuality480`640`80700`1024`721536`1536`642048`1536` (widest)64**Precedence.** A [per-image quality override](#per-image-compression) always wins for that file — when set, the curve is not consulted. Otherwise the curve applies. With neither, the format's base `parameters` quality is used unchanged.

**Lossy only.** The curve is skipped for lossless parameters (those containing `lossless=true`), so the default lossless PNG/GIF settings are never touched — only lossy output is scaled.

Note

Like the global `parameters` quality, changing a curve does not regenerate existing siblings. Clear processed files (*Admin Tools → Maintenance → Remove Temporary Assets*) to apply a new curve.

Async mode
----------

[](#async-mode)

By default the extension converts images synchronously inside the request that processes the source file. On image-heavy pages or large-fileadmin sites this adds latency to every render. Enabling `async = 1` moves the conversion off the render path:

1. Set `async = 1` in the extension configuration.
2. Run TYPO3's database analyzer so `tx_webp_queue` is created.
3. Register a TYPO3 Scheduler task: **System → Scheduler → Add task → Type: "Process conversion queue (webp)"**. Pick a frequency that matches your throughput (every minute for busy sites, hourly for low-traffic).
4. Make sure the scheduler itself runs — either via `vendor/bin/typo3 scheduler:run` in cron, or a daemonized runner.

From now on the listener queues new conversions and the scheduler runs them in the background. Existing siblings keep working; images that don't have one yet get converted the next time they're rendered.

### Sweeping non-FAL folders

[](#sweeping-non-fal-folders)

Some image folders (notably `typo3temp/assets/online_media/` for YouTube/Vimeo preview thumbnails) live outside TYPO3's File Abstraction Layer, so the listener never sees them. The `--folder` argument bypasses the queue and converts files directly:

```
vendor/bin/typo3 webp:process-queue --folder=typo3temp/assets/online_media/
```

Register this as a second Scheduler task ("Execute console command") if you want it to run periodically. Paths resolve relative to the public web root and are restricted to it for safety.

Webserver configuration
-----------------------

[](#webserver-configuration)

Tip

Run `./vendor/bin/typo3 webp:webserver-config --server=nginx` (or `apache` / `caddy`) to print a ready-to-paste snippet generated for **your** enabled formats and source types — with the AVIF→WebP→JXL priority already correct. The hand-written recipes below are the same output, shown in full for reference (including the Cloudflare and user-agent variants the command points to).

The webserver inspects the client's `Accept` header and rewrites the request to the best-matching sibling that's available on disk. If only WebP is enabled, the server has two candidates: serve `.webp` when the client accepts it, otherwise fall back to the original JPEG/PNG/GIF. With AVIF or JPEG XL enabled too, the server picks among the available siblings in client-preference order.

Below are the full hand-written examples for nginx, Apache, and Caddy. The `webp:webserver-config` command above generates these same negotiation rules tailored to your enabled formats — paste the output into your own server or vhost context. The E2E suite injects that generated output into per-server scaffolds ([nginx.conf](Tests/E2E/nginx.conf), [apache.conf](Tests/E2E/apache.conf), [caddy.conf](Tests/E2E/caddy.conf)) and runs real nginx, Apache, and Caddy against them, so the generated config is verified to negotiate correctly.

### Which blocks do I need?

[](#which-blocks-do-i-need)

Generate rules **only for the formats your install actually produces** (the [`formats_enabled`](#formats_enabled) setting), and always list them in this fixed preference order — **AVIF → WebP → JPEG XL**. The first match wins, so the wrong order is the single most common reason only one format ever gets served.

`formats_enabled`Keep these rules`webp`WebP only`webp,avif`AVIF + WebP (AVIF first)`webp,avif,jxl`all three, AVIF → WebP → JXLDelete the blocks for any format you didn't enable; each per-server example below is shown with all three formats.

Important

Make sure no earlier rule in your config short-circuits the request for the image extensions you target (e.g. a generic static-asset block). If so, move the sibling-rewrite rules above it or rework the earlier rule.

### nginx

[](#nginx)

Add a `map` directive in the `http` block. Order matters — the first match wins, so list the formats in preference order (AVIF first, WebP next, JXL last):

```
map $http_accept $sibling_suffix {
    default        "";
    "~*image/avif" ".avif";
    "~*image/webp" ".webp";
    "~*image/jxl"  ".jxl";
}
```

If you only generate `.webp`, the map can be the single-line `"~*webp" ".webp";` variant — clients never ask for `image/avif` from a server that doesn't offer it.

If you front the site with Cloudflare, prefer this variant — Cloudflare caches per response and would otherwise mix the variants:

```
map $http_accept $sibling_suffix_raw {
    default        "";
    "~*image/avif" ".avif";
    "~*image/webp" ".webp";
    "~*image/jxl"  ".jxl";
}
map $http_cf_cache_status $iscf {
    default   1;
    ""        0;
}
# Suppress the sibling whenever Cloudflare is in front (iscf=1). Composite key
# is "": "0.avif" serves AVIF directly, "1.avif" serves the
# original. Every iscf=1 case falls through `default ""`.
map $iscf$sibling_suffix_raw $sibling_suffix {
    default   "";
    "0.avif"  ".avif";
    "0.webp"  ".webp";
    "0.jxl"   ".jxl";
}
```

Add the location block to your `server`:

```
location ~* ^.+\.(png|gif|jpe?g)$ {
    add_header Vary "Accept";
    add_header Cache-Control "public, no-transform";
    try_files $uri$sibling_suffix $uri =404;
}
```

#### Restrict by user agent (optional)

[](#restrict-by-user-agent-optional)

```
location ~* ^.+\.(png|gif|jpe?g)$ {
    if ($http_user_agent !~* (Chrome|Firefox|Edge)) {
        set $sibling_suffix "";
    }
    …
}
```

### Apache

[](#apache)

The first two directives are already part of TYPO3's default `.htaccess` template (`typo3/sysext/install/Resources/Private/FolderStructureTemplateFiles/root-htaccess`); they're shown here for completeness. Assume `mod_rewrite.c` is enabled.

```
RewriteEngine On
AddType image/webp .webp
AddType image/avif .avif
AddType image/jxl  .jxl

# AVIF preferred over WebP — order matters, first matching rule wins.
RewriteCond %{HTTP_ACCEPT} image/avif
RewriteCond %{REQUEST_FILENAME} (.*)\.(?i:png|gif|jpe?g)$
RewriteCond %{REQUEST_FILENAME}\.avif -f
RewriteRule ^ %{REQUEST_FILENAME}\.avif [L,T=image/avif]

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.*)\.(?i:png|gif|jpe?g)$
RewriteCond %{REQUEST_FILENAME}\.webp -f
RewriteRule ^ %{REQUEST_FILENAME}\.webp [L,T=image/webp]

RewriteCond %{HTTP_ACCEPT} image/jxl
RewriteCond %{REQUEST_FILENAME} (.*)\.(?i:png|gif|jpe?g)$
RewriteCond %{REQUEST_FILENAME}\.jxl -f
RewriteRule ^ %{REQUEST_FILENAME}\.jxl [L,T=image/jxl]

        Header append Vary Accept

```

If you only generate `.webp` (default `formats_enabled = webp`), keep just the WebP block and drop the AVIF/JXL ones.

#### When `%{REQUEST_FILENAME}` doesn't resolve

[](#when-request_filename-doesnt-resolve)

Some environments — shared hosting (IONOS etc.), Windows Apache, or setups where the rewrite runs before path resolution — return 403/404 with the `%{REQUEST_FILENAME}` form because Apache can't map the request to a filesystem path at that stage. Two portable alternatives:

```
RewriteRule ^ %{REQUEST_URI}.webp [L,T=image/webp]
```

or:

```
RewriteRule ^(.*)$ $1.webp [L,T=image/webp]
```

Substitute either for the `RewriteRule ^ %{REQUEST_FILENAME}\.webp …` line above.

#### Restrict by user agent (optional)

[](#restrict-by-user-agent-optional-1)

```
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{HTTP_USER_AGENT} ^.*(Chrome|Firefox|Edge).*$ [NC]
…
```

### Caddy

[](#caddy)

Caddy negotiates on the `Accept` header with one `map` per format and a single `try_files` in preference order. Because the sibling naming matches this extension (`photo.jpg.avif`), the public URL never changes — `try_files` just serves the first sibling that exists. Place this inside your site block; it assumes a `file_server` (and `root`) is already configured, as in a standard TYPO3 Caddy vhost:

```
map {header.Accept} {avif_suffix} {
    ~image/avif avif
    default     ""
}
map {header.Accept} {webp_suffix} {
    ~image/webp webp
    default     ""
}
map {header.Accept} {jxl_suffix} {
    ~image/jxl  jxl
    default     ""
}

@images {
    path_regexp \.(png|gif|jpe?g)$
}
handle @images {
    header Vary Accept
    try_files {path}.{avif_suffix} {path}.{webp_suffix} {path}.{jxl_suffix} {path} =404
}
```

`try_files` lists the formats in preference order (AVIF → WebP → JPEG XL); Caddy serves the first sibling present on disk and falls back to the original. A format the client didn't ask for expands to an empty suffix (`{path}.`), which never matches a real file and is skipped.

If you only generate `.webp`, reduce it to the single `webp_suffix` map and `try_files {path}.{webp_suffix} {path}`.

Note

Caddy derives `Content-Type` from the **served sibling's** extension (via Go's MIME database and your system `mime.types`). `.webp` and `.avif` usually resolve out of the box; if `.jxl` comes back as `application/octet-stream`, add `image/jxl jxl` to your `mime.types`. Verify with `curl -I` as in [Verifying it works](#verifying-it-works).

#### Restrict by user agent (optional)

[](#restrict-by-user-agent-optional-2)

Add a `header User-Agent` condition to the `@images` matcher — requests from other agents skip the `handle` and fall through to the original file:

```
@images {
    path_regexp \.(png|gif|jpe?g)$
    header User-Agent *Chrome* *Firefox* *Edge*
}
```

Remote storages (S3, Azure, custom FAL drivers)
-----------------------------------------------

[](#remote-storages-s3-azure-custom-fal-drivers)

[![Generate WebP / AVIF / JPEG XL siblings storage setting](Documentation/generate_webp_variants.png)](Documentation/generate_webp_variants.png)

Out of the box every Local writable storage produces sibling files — that's the default mode for the *Generate WebP / AVIF / JPEG XL siblings* field on each storage record. To opt in a non-Local storage (S3 mount, Azure mount, any custom FAL driver), edit the storage record and set the field to **Enabled**.

ValueResult**Auto** *(default)*On for `driver = Local`, off for everything else. Identical to pre-14.2 behaviour.**Enabled**On regardless of driver type. Use to opt a remote storage in.**Disabled**Off regardless of driver type. Use to take a Local storage out of the pipeline temporarily.Once enabled, behaviour is identical to a Local storage: every sibling lands at `.` on the storage, and the four FAL lifecycle events (move, replace, delete, recycler) keep all siblings in sync.

Important

Enable [`async = 1`](#async) for any storage with a non-Local driver. Synchronous mode adds the driver's upload latency to every page render that processes an image (typical S3 PUT: 100–500 ms, more on cold connections). The async queue moves that work off the render path.

### Serving the right format on a CDN

[](#serving-the-right-format-on-a-cdn)

This extension *writes* the siblings on the storage. Serving the right one per request — the `Accept`-header rewrite — is the edge's job. Sketches:

- **CloudFront**: attach a CloudFront Function on viewer request that inspects `Accept`. Pick `.avif` if present, fall through to `.webp`, fall through to `.jxl` for clients that prefer it (Safari 17+), otherwise serve the original. Pair with a viewer-response function that sets `Vary: Accept`.
- **Cloudflare**: a Worker doing the same priority lookup, or an Image Resizing policy if the account has it.
- **Direct S3 origins without an edge function**: not supported by S3 itself; you need a layer in front (CloudFront/equivalent or an origin proxy).

The webserver-rewrite recipes above still apply when TYPO3's origin sits in front of the storage (e.g., S3 mounted only for backend uploads, but served through the TYPO3 instance).

Verifying it works
------------------

[](#verifying-it-works)

Two things to check: that sibling files are actually generated for every format you enabled, and that the webserver serves the right one when the client supports it.

### Sibling file generation

[](#sibling-file-generation)

Browse to `fileadmin/_processed_` and look for siblings next to processed variants:

```
csm_foo-bar_4f3d6bb7d0.jpg            ← TYPO3 variant
csm_foo-bar_4f3d6bb7d0.jpg.webp       ← formats_enabled contains webp
csm_foo-bar_4f3d6bb7d0.jpg.avif       ← formats_enabled contains avif
csm_foo-bar_4f3d6bb7d0.jpg.jxl        ← formats_enabled contains jxl

```

With `convert_all = 1`, you'll also find siblings next to originals in `fileadmin/` itself.

### Delivery

[](#delivery)

Request a JPEG/PNG with an `Accept` header for each enabled format:

```
# Expect Content-Type matching the highest-priority enabled format the client asked for:
curl -H "Accept: image/avif,image/webp,image/jxl" -I https://example.tld/fileadmin/_processed_/b/2/csm_foo-bar_4f3d6bb7d0.jpg
# expect: Content-Type: image/avif   (or image/webp if only webp is enabled, etc.)
```

Or open the URL in a browser and check the response headers in the developer tools — despite the `.jpg` suffix the `Content-Type` should be one of the modern formats:

[![Response headers showing image/webp](Documentation/headers.png)](Documentation/headers.png)

Diagnosing your installation
----------------------------

[](#diagnosing-your-installation)

The `webp:diagnose` CLI command walks the full delivery chain end-to-end — across every enabled output format — and points at the first failing link.

```
vendor/bin/typo3 webp:diagnose                              # health check
vendor/bin/typo3 webp:diagnose --url=https://example.com    # also probe webserver delivery
vendor/bin/typo3 webp:diagnose --file=42                    # also investigate one file
vendor/bin/typo3 webp:diagnose --format=avif                # limit the report to one format
```

It reports per enabled format:

- Storages: mode, driver, per-format sibling count, plus phantom rows with unregistered drivers.
- Converter: class, per-format delegate availability (`convert -list format` for Magick; `vips_foreign_find_save` for libvips), parameter parsing.
- Async pipeline: per-format queue size + oldest age, scheduler task state.
- Failed-conversion cache: per-format totals, recent rows, dominant config hash.
- Delivery probe (`--url=…`): four `Accept` HEADs (avif / jxl / webp / `*/*`) compared against `expectedTopFormat`, plus `Vary: Accept`.
- File deep dive (`--file=`): metadata + per-format sibling presence (source-folder and processed-folder) + per-format failed-attempts rows.

**Limitation:** the probe runs from this machine. CDN behaviour at the edge can differ from what you observe locally. Run the probe from a host inside your CDN's pull zone for the most accurate read.

Useful flags:

FlagPurpose`--format=`Limit the report to one output format`--insecure`Disable TLS certificate verification on the HTTP probe — for self-signed or otherwise untrusted certs`--probe-timeout=`HTTP probe timeout (default: 10)Troubleshooting
---------------

[](#troubleshooting)

Every conversion problem is logged to TYPO3's log (`var/log/typo3_*.log` by default). Start there.

Common cases:

SymptomLikely causeNo sibling files appear in `_processed_/`Converter binary lacks the delegate for the enabled format(s) (`webp:diagnose` reports this), or `mime_types_` excludes the sourceFiles are bigger than the originalAutomatically removed and **not retried** with the same configurationOutput renders darker / off-colour`$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_colorspace']` (e.g. `sRGB`)Apache rewrite returns 403/404[`%{REQUEST_FILENAME}` doesn't resolve](#when-request_filename-doesnt-resolve)File still served as JPEG after a successful generationWebserver rewrite rule missing or shadowed by another ruleOnly one format is served when several are enabledRewrite rule lists the formats in the wrong priority order — AVIF should come before WebP, see [Webserver configuration](#webserver-configuration)Sibling left behind after deleting the sourceNone — fixed in 14.0.0; upgradeLarge/high-resolution originals fail or time out, or produce no siblingSee [Very large or high-resolution originals](#very-large-or-high-resolution-originals)WebP/AVIF looks softer or blurrier than the JPEGSee [Sharp output](#sharp-output)After changing `processor_colorspace`, clean up any processed files via the Maintenance backend module (*System → Maintenance → Remove Temporary Assets* on TYPO3 v14; *Admin Tools → Maintenance* on v12/v13) so the change takes effect on existing images.

### Very large or high-resolution originals

[](#very-large-or-high-resolution-originals)

Multi-megabyte originals (e.g. 4000px+ photos) rendered into several responsive widths are where conversion most often struggles: ImageMagick can run out of memory or hit the request time limit, and at the default quality the largest WebP can come out *bigger* than the source and is dropped (so that variant gets no sibling at all). Three settings, which combine well, address this:

- **Use the [`VipsConverter`](#parameters).** libvips converts large images with far less memory and 2–3× faster than ImageMagick, which removes the usual memory/timeout failures on big originals.
- **Enable [`async`](#async-mode).** Conversions move off the page-render request to a scheduler worker, so a slow or heavy conversion can never fail or delay the frontend response.
- **Configure a [width-to-quality curve](#compress-larger-variants-harder).** Large variants are compressed harder, so they stay smaller than the original and actually produce a sibling — instead of being rejected for exceeding the source size.

### Sharp output

[](#sharp-output)

TYPO3 core sharpens generated JPEGs but not WebP/AVIF, so images converted *directly* to WebP can look softer. This extension avoids that: it converts the **already-processed image variant** — the cropped, scaled, and (for JPEG) sharpened intermediate TYPO3 produced — so the sibling inherits that sharpening rather than re-deriving a soft one from the original.

If you still want extra sharpening, the `MagickConverter` passes its [`parameters`](#parameters) straight to ImageMagick, so you can append a sharpen operator per mime type, e.g. `image/jpeg::-quality 85 -unsharp 0x0.75+0.75+0.008`. The `VipsConverter` applies encoder save-options only and has no sharpening parameter — choose `MagickConverter` for that format if you need it.

Known limitations
-----------------

[](#known-limitations)

- **Animated GIFs.** Only the libvips routes preserve animation: `VipsConverter` does it automatically, and the `vips` CLI route requires `%s[n=-1]` on the GIF source argument (see [`parameters`](#parameters)). `MagickConverter`, `PhpGdConverter`, and `cwebp`-based configurations produce single-frame output. For AVIF and JPEG XL siblings, animation preservation depends on the chosen converter and is not exercised by the test suite.
- **The image processor must be compiled with the right delegate for each enabled format.** WebP needs the libwebp delegate; AVIF needs libheif with an AV1 encoder; JPEG XL needs libjxl. See [Requirements](#requirements).
- **Cross-storage FAL moves are not handled.** If you move a file between two different storages, the sibling at the source storage is left orphaned. Lazy regeneration handles the target storage on next render. Single-storage moves work correctly.
- **`use_system_settings` only applies to `MagickConverter`.** `PhpGdConverter` and external-binary configurations ignore it.

Maintenance
-----------

[](#maintenance)

To remove all generated sibling files (e.g. before a converter or quality change):

1. *System → Maintenance → Remove Temporary Assets* (TYPO3 v14) or *Admin Tools → Maintenance → Remove Temporary Assets* (v12/v13).
2. Click *Scan temporary files*.
3. Click the button labelled with the storage path.

The button label only mentions `_processed_/`, but all processed files in the storage are removed — including every format's sibling.

The next page render will regenerate siblings for every currently-enabled format using the current configuration.

Drawbacks
---------

[](#drawbacks)

- **Extra CPU.** Every processed image is reprocessed once per enabled output format. The work happens once per (image × format) pair (results are cached on disk) but adds latency to first-time renders. AVIF and JPEG XL encoders are slower than WebP; budget CPU accordingly when enabling them.
- **Extra disk.** Each enabled format adds one sibling per source image. Typical relative sizes vs the original:

    - WebP: ~65–75% (Google's reference numbers — lossy WebP is 25–34% smaller than JPEG; lossless is 26% smaller than PNG)
    - AVIF: ~45–55% at equal SSIM
    - JPEG XL: comparable to AVIF, often better on lossless content

    With `convert_all = 1` enabled this applies to every source image, not just processed variants — and is multiplied by the number of enabled formats.

Alternatives
------------

[](#alternatives)

- **TYPO3 core image conversion** — see [the comparison above](#when-to-use-this-vs-typo3-core-image-conversion). Best fit when you can change URLs.
- **Apache `mod_pagespeed` / nginx `ngx_pagespeed`** — Google's automatic image-rewriting modules. Equal end-result with `pagespeed EnableFilters convert_jpeg_to_webp;` plus `convert_to_webp_lossless;`, but more involved to set up and operate.
- **Cloudflare Polish** or similar CDN-level image optimisation.

Credits
-------

[](#credits)

Inspired by [Angela Dudtkowski](https://www.clickstorm.de/agentur/)'s `cs_webp` extension. Thanks Angela.

Thanks to Xavier Perseguers for the Cloudflare hint and to Marcus Förster for simplifying the Apache rewrite rules.

License
-------

[](#license)

GPL-3.0-or-later — see [LICENSE](LICENSE).

Spread some love
----------------

[](#spread-some-love)

Send us a postcard from your favourite place and tell us how much you love TYPO3 and OpenSource:

> plan2net GmbH Sieveringerstraße 37 1190 Vienna, Austria

###  Health Score

72

—

ExcellentBetter than 100% of packages

Maintenance96

Actively maintained with recent releases

Popularity55

Moderate usage in the ecosystem

Community32

Small or concentrated contributor base

Maturity89

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 89.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~68 days

Recently: every ~1 days

Total

45

Last Release

17d ago

Major Versions

2.2.3 → 3.0.02020-03-10

3.3.1 → 4.0.02021-10-04

4.2.0 → 5.0.02023-04-26

4.3.2 → 13.0.02025-06-30

13.0.1 → 14.0.02026-05-14

PHP version history (4 changes)1.2.0PHP &gt;=7.0.0

3.0.0PHP &gt;=7.2.0

5.0.0PHP &gt;=8.1

13.0.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4ea950f22b43e010ba4f0a6effb0928a6a1d11f64d36cec0d030b757bdfa85e?d=identicon)[wazum](/maintainers/wazum)

![](https://www.gravatar.com/avatar/fdc5d7c9be0f04c0d84c56db1e263fb7cb88c40564a7c293f1a2d4aa543f0115?d=identicon)[plan2net@packagist](/maintainers/plan2net@packagist)

---

Top Contributors

[![wazum](https://avatars.githubusercontent.com/u/146727?v=4)](https://github.com/wazum "wazum (177 commits)")[![richardkrikler](https://avatars.githubusercontent.com/u/57064056?v=4)](https://github.com/richardkrikler "richardkrikler (4 commits)")[![infabo](https://avatars.githubusercontent.com/u/3999104?v=4)](https://github.com/infabo "infabo (3 commits)")[![masi](https://avatars.githubusercontent.com/u/690355?v=4)](https://github.com/masi "masi (2 commits)")[![georgringer](https://avatars.githubusercontent.com/u/1905663?v=4)](https://github.com/georgringer "georgringer (2 commits)")[![eliashaeussler](https://avatars.githubusercontent.com/u/16313625?v=4)](https://github.com/eliashaeussler "eliashaeussler (2 commits)")[![rubsilv](https://avatars.githubusercontent.com/u/39330651?v=4)](https://github.com/rubsilv "rubsilv (2 commits)")[![Patta](https://avatars.githubusercontent.com/u/2151127?v=4)](https://github.com/Patta "Patta (1 commits)")[![peterkraume](https://avatars.githubusercontent.com/u/4234704?v=4)](https://github.com/peterkraume "peterkraume (1 commits)")[![ischmittis](https://avatars.githubusercontent.com/u/904789?v=4)](https://github.com/ischmittis "ischmittis (1 commits)")[![Kanti](https://avatars.githubusercontent.com/u/471387?v=4)](https://github.com/Kanti "Kanti (1 commits)")[![franzkugelmann](https://avatars.githubusercontent.com/u/11320147?v=4)](https://github.com/franzkugelmann "franzkugelmann (1 commits)")

---

Tags

avifcontent-negotiationcore-web-vitalsextensiongraphicsmagickimage-conversionimage-optimizationimagemagickjpeg-xljxllibvipsphptypo3typo3-cmstypo3-extensionweb-performancewebp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/plan2net-webp/health.svg)

```
[![Health](https://phpackages.com/badges/plan2net-webp/health.svg)](https://phpackages.com/packages/plan2net-webp)
```

###  Alternatives

[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

103519.9k53](/packages/friendsoftypo3-content-blocks)[symfony/framework-bundle

Provides a tight integration between Symfony components and the Symfony full-stack framework

3.6k251.7M11.6k](/packages/symfony-framework-bundle)[typo3/cms-fluid

TYPO3 CMS Fluid Integration - Integration of the Fluid templating engine into TYPO3.

1912.9M646](/packages/typo3-cms-fluid)[typo3/cms-install

TYPO3 CMS Install Tool - The Install Tool is used for installation, upgrade, system administration and setup tasks.

1812.3M495](/packages/typo3-cms-install)[netresearch/rte-ckeditor-image

Image support in CKEditor for the TYPO3 ecosystem - by Netresearch

611.1M8](/packages/netresearch-rte-ckeditor-image)[api-platform/symfony

Symfony API Platform integration

384.5M128](/packages/api-platform-symfony)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
