# laravel-image-optimizer optimizes selected image uploads with a chain of binaries

> spatie/laravel-image-optimizer is the Laravel 6 and up integration of spatie/image-optimizer, and it optimizes PNGs, JPGs, SVGs and GIFs by running them through a chain of external tools, detecting which binaries are installed and using them, with a facade, a container-resolved chain and a middleware for images in a request. The configuration is a published PHP file with per-optimizer arguments, and the operational reality is that the binaries have to be on the server.

**spatie/laravel-image-optimizer** — Optimize images in your Laravel app

- Repository: https://github.com/spatie/laravel-image-optimizer
- Website: https://spatie.be/opensource/laravel
- Stars: 1,307 · Forks: 116
- Language: PHP
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/spatie-laravel-image-optimizer

## A framework wrapper around a framework-agnostic package

The package is the Laravel 6.0 and up specific integration of spatie/image-optimizer, and it can optimize PNGs, JPGs, SVGs and GIFs by running them through a chain of various image optimization tools. The key mechanic is that the package automatically detects which optimization binaries are installed on your system and uses them, which means the same code works on a developer laptop with one tool and a production server with six. The layering is the point. If you do not use Laravel, the README says no problem, and you use the underlying spatie/image-optimizer directly, and the Laravel package is the integration rather than the engine. The audience is a Laravel application that accepts uploads, and the value is that the optimisation happens where the file already is, rather than in a separate worker that has to be deployed and monitored.

## The API is three lines long, in two shapes

The usage is deliberately small, and there are two ways to call it. The facade version takes a path and replaces the file with an optimised version:

```php
use ImageOptimizer;

// the image will be replaced with an optimized version which should be smaller
ImageOptimizer::optimize($pathToImage);

// if you use a second parameter the package will not modify the original
ImageOptimizer::optimize($pathToImage, $pathToOptimizedImage);
```

And if you do not like facades, you resolve a configured instance of Spatie\ImageOptimizer\OptimizerChain out of the container, which is the same behaviour with the same two arguments:

```php
app(Spatie\ImageOptimizer\OptimizerChain::class)->optimize($pathToImage);
```

The second argument is the one to notice, because it separates the output from the input, and that is what you want in a pipeline where the original must be kept, or where the optimised copy goes to a different storage bucket. The first call replaces the file in place, which is the simplest thing and also the one that cannot be undone.

## The middleware optimises images in a request

For uploaded images there is a middleware, and it is registered in the HTTP kernel as an alias:

```php
// app/Http/Kernel.php
protected $middlewareAliases = [
   ...
   'optimizeImages' => \Spatie\LaravelImageOptimizer\Middlewares\OptimizeImages::class,
];
```

The README says that all images in requests to routes that use the optimizeImages middleware will be optimised, which is the shape most teams want, since an upload is a request and the file is right there. The alternative is to call the optimizer yourself in a controller or in a queued job after the upload is stored, and the trade is immediate versus deferred. The middleware runs in the request, so an image of a few megabytes adds the time of the optimizers to the response, and the configuration has a timeout setting for exactly that reason, described as the maximum time in seconds each optimizer is allowed to run separately, with a default of 60. A second setting controls logging, log_optimizer_activity, which is false by default and can also be set to a class implementing the PSR logger interface.

## The published config is where the real decisions live

The package comes with sane defaults and the configuration is published with a vendor publish command:

```bash
php artisan vendor:publish --provider="Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider"
```

The published file is a PHP array mapping each optimizer class to the arguments it is called with, and reading it tells you what the package actually does to a file. Jpegoptim is called with -m85 to set the maximum quality to 85 percent, --strip-all to strip text information such as comments and EXIF data, and --all-progressive so the result is a progressive image. Pngquant is called with --force, which the comment marks as a required parameter. Optipng is called with -i0 for a non-interlaced, progressive scanned image, -o2 for the optimization level of two, which means multiple IDAT compression trials, and -quiet. Svgo is called with --disable=cleanupIDs, and the comment says it is disabled because it is known to cause trouble. Gifsicle is called with -b and -O3, which produces the slowest but best results. And Cwebp is called with -m 6 for the slowest compression method, -pass 10 to maximise the amount of analysis pass, -mt for multithreading and -q 90 for the quality factor that brings the least noticeable changes. That last argument is the one to think about, since converting to WebP at quality 90 is a deliberate decision about file size against fidelity.

## The binaries are the real dependency

The operational part of this package is that it does not contain the optimizers. The package uses a bunch of binaries to optimize images, and the README sends you to the optimization tools section of the underlying image-optimizer package to learn which ones and how to install them, and that same section contains the information on what these tools will do to your images. That ordering matters for a deployment. A composer install on a server that does not have jpegoptim, pngquant, optipng, svgo, gifsicle or cwebp on the path will still succeed, because the package detects what is there and uses what it finds, so the failure mode is a quietly unoptimised image rather than an error. The second half of the operational picture is the timeout, and the third is the logging switch, which is the difference between seeing what the optimizers did and not knowing why a file is still large. The package itself registers itself, so there is no service provider to add and no boot step to schedule.

## Where it fits, and what you give up

The scope is upload-time optimisation of the formats a web application actually receives, and the design assumes the original is either disposable or kept deliberately. That assumption is where the limits are. The chain applies the same arguments to every file, so a screenshot of a chart and a photograph of a product get the same treatment, and a team that wants per-asset decisions has to bypass the chain. The second limit is the lossiness of the default configuration, since -m85 on jpegoptim and -q 90 on cwebp are lossy choices made for you, and the README's own comments describe them as quality factors that bring the least noticeable changes, which is a judgement rather than a guarantee. The third is that the middleware runs in the request, so on a slow filesystem the user waits for the optimizers, and the timeout of 60 seconds per optimizer is a ceiling rather than a typical value. What the package gives up in exchange is the infrastructure: no queue, no worker, no separate image service, and the framework-agnostic engine underneath means you can move the same behaviour to a command line job later.

## Conclusion

laravel-image-optimizer is the right dependency if your application accepts image uploads and you want them compressed without writing a job, a queue worker and a container with a dozen tools in it, because the middleware makes the optimisation happen on the way in and the configuration file makes the tradeoffs explicit. It is the wrong tool if you cannot install native binaries on the host, since every optimizer is an external program and a container image without them will silently do nothing useful, and the wrong tool if you need lossy-to-lossless decisions per asset, since the chain applies the same arguments to every file. Before you adopt it, read the optimization tools section of the underlying package and install only the binaries you actually need, and consider publishing the config and choosing the JPEG quality setting for your image-quality and file-size requirements rather than accepting the default blindly.

## FAQ

### What does spatie/laravel-image-optimizer do?

It is the Laravel 6 and up integration of spatie/image-optimizer, and it optimizes PNGs, JPGs, SVGs and GIFs by running them through a chain of external image optimization tools, automatically detecting which optimization binaries are installed on the system and using them.

### How do I install and configure the package?

Install it with composer require spatie/laravel-image-optimizer, and the package registers itself. To change the defaults, publish the config file with php artisan vendor:publish --provider="Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider", which gives you the per-optimizer arguments, the timeout and the logging switch.

### How do I optimize images that are uploaded to my application?

Add the OptimizeImages middleware in the HTTP kernel, registering it as an alias such as 'optimizeImages' => \Spatie\LaravelImageOptimizer\Middlewares\OptimizeImages::class. All images in requests to routes that use the middleware will then be optimized.

### What are the external binaries this package needs?

The optimizers are jpegoptim, pngquant, optipng, svgo, gifsicle and cwebp, and the package detects which are installed and uses only those. The README points at the optimization tools section of the underlying spatie/image-optimizer package for how to install them and what they do to your images.

## Sources

- [License: MIT](https://github.com/spatie/laravel-image-optimizer/blob/main/LICENSE)
- [Project website](https://spatie.be/opensource/laravel)
- [README](https://github.com/spatie/laravel-image-optimizer/blob/main/README.md)
- [Releases](https://github.com/spatie/laravel-image-optimizer/releases)
- [spatie/laravel-image-optimizer on GitHub](https://github.com/spatie/laravel-image-optimizer)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spatie-laravel-image-optimizer
