Advanced Usage
Once you are comfortable building URLs, there are a handful of features worth knowing about: named instances, presets, cache busting, server-side presets, per-URL security caps, and the raw escape hatch.
The Multi-Instance Manager
Most applications need a single imgproxy server, but some need several — staging versus production, or separate servers with different credentials. The package supports any number of named instances, each with its own server, credentials, and encoding.
To target a non-default instance, call Imgproxy::instance():
$url = Imgproxy::instance('staging')
->image('https://example.com/image.jpg')
->resize(ResizeType::Fill, 800, 600)
->url();Instances are defined in config/laravel-imgproxy.php:
'instances' => [
'default' => [
'url' => env('IMGPROXY_URL'),
'key' => env('IMGPROXY_KEY'),
'salt' => env('IMGPROXY_SALT'),
'signature_size' => null,
'encoding' => 'base64',
],
'staging' => [
'url' => 'https://imgproxy-staging.example.com',
'key' => '...',
'salt' => '...',
'signature_size' => 16,
'encoding' => 'base64',
],
],The default key at the top of the config file determines which instance is used when no name is passed to Imgproxy::instance() or imgproxy().
Named Presets
Presets are reusable sets of processing options defined in config and shared across instances. They compose onto the builder before per-URL overrides.
Defining Presets
Define presets in config/laravel-imgproxy.php under the presets key. Each preset maps a fluent method name to its value:
'presets' => [
'thumb' => [
'resize' => 'fill',
'width' => 300,
'height' => 300,
],
'hero' => [
'resize' => 'fill',
'width' => 1200,
'height' => 600,
'quality' => 85,
],
],Applying Presets
Call applyPreset() with the key name. Options chained after the preset override it:
// Preset sets width:300; override sets width:640
$url = Imgproxy::image($source)
->applyPreset('thumb')
->width(640)
->url();
// rs:fill:300:300/w:640/...How Preset Composition Works
Presets are expanded into their individual option segments and appended to the URL in order. Options chained after applyPreset() land later in the segment chain, so they override earlier values — imgproxy processes options left to right, and the last one wins:
$url = Imgproxy::image($source)
->applyPreset('hero') // rs:fill:1200:600/q:85
->quality(90) // overrides q:85 with q:90
->url();
// .../rs:fill:1200:600/q:85/q:90/...Rules and Constraints
- Preset keys must match fluent method names. The key
resizemaps toresize(),widthmaps towidth(), and so on. - Only single-value options are supported. A preset entry like
'width' => 300works; variadic options likewithOption()cannot be expressed in a preset. - Unknown presets throw. Calling
->applyPreset('nonexistent')throwsInvalidArgumentException. - Invalid values throw. A preset with an invalid resize type or out-of-range quality triggers the same validation as a direct method call.
Cache Busting
Append a version string to invalidate CDN, proxy, and browser caches. The buster becomes part of the URL path, so changing it forces a fresh fetch:
Imgproxy::image($source)->cacheBuster('v2')->url();
// cb:v2This is commonly tied to a file's updated timestamp or a content hash.
Expiration
Set a Unix timestamp after which imgproxy returns 404. Pass 0 to disable expiration:
// Expires in 1 hour
Imgproxy::image($source)->expires(now()->addHour())->url();
// exp:1723228800
// No expiration
Imgproxy::image($source)->expires(0)->url();
// exp:0Filename
Set the filename in the Content-Disposition header for downloads:
Imgproxy::image($source)->filename('photo.jpg')->url();
// fn:photo.jpgWhen the filename is already URL-safe base64 encoded, pass encoded: true:
Imgproxy::image($source)->filename($encodedName, encoded: true)->url();
// fn:<base64>:1Return Attachment
Force the browser to download the image instead of displaying it inline:
Imgproxy::image($source)->returnAttachment()->url();
// att:1Server-Side Presets
imgproxy itself supports presets defined on the server (via IMGPROXY_PRESETS / IMGPROXY_PRESETS_PATH). Reference them with preset(), which emits the pr: segment:
Imgproxy::image($source)->preset('blog-cover')->url();
// pr:blog-coverPass multiple server-side preset names to apply them in order:
Imgproxy::image($source)->preset('blog-cover', 'sharpen')->url();
// pr:blog-cover:sharpenWARNING
Server-side presets are a separate mechanism from the client-side presets defined in config/laravel-imgproxy.php. If the server does not have the preset registered, imgproxy responds with 500.
The withOption() Escape Hatch
Append any imgproxy processing segment verbatim, without validation. Use this for options not yet covered by a typed method:
Imgproxy::image($source)->withOption('some:new:option')->url();
// some:new:optionThe segment is appended in call order, just like any other method:
$url = Imgproxy::image($source)
->width(800)
->withOption('some:new:option')
->quality(80)
->url();
// w:800/some:new:option/q:80TIP
Prefer typed methods when they are available — they validate inputs and catch errors early. withOption() skips all validation.
Security Caps
The imgproxy server enforces limits on source resolution, file size, and animation complexity. You can tighten these per-URL when the server has security options enabled:
// Max source resolution: 5 megapixels
Imgproxy::image($source)->maxSourceResolution(5)->url();
// msr:5
// Max source file size: 10 MB
Imgproxy::image($source)->maxSourceFileSize(10485760)->url();
// msfs:10485760
// Max animation frames: 50
Imgproxy::image($source)->maxAnimationFrames(50)->url();
// maf:50
// Max animation frame resolution: 2 megapixels
Imgproxy::image($source)->maxAnimationFrameResolution(2)->url();
// mafr:2
// Max result dimension: 4000px
Imgproxy::image($source)->maxResultDimension(4000)->url();
// mrd:4000These cap what the server is willing to process for a given request. They do not replace the server's own security configuration — they let you tighten limits per-URL.