PHPackages                             aaronfrancis/imgproxy - 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. aaronfrancis/imgproxy

ActiveLibrary[Image &amp; Media](/categories/media)

aaronfrancis/imgproxy
=====================

On-the-fly image resizing and format conversion for Laravel

v0.1.0(4mo ago)216MITPHPPHP ^8.2CI passing

Since Dec 28Pushed 4mo agoCompare

[ Source](https://github.com/aarondfrancis/imgproxy)[ Packagist](https://packagist.org/packages/aaronfrancis/imgproxy)[ RSS](/packages/aaronfrancis-imgproxy/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (8)Versions (3)Used By (0)

ImgProxy for Laravel
====================

[](#imgproxy-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5051fa3f4dd9f5c31faf16d5988eea147e740a8cbae5bef621511f8fbd344782/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6161726f6e6672616e6369732f696d6770726f78792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aaronfrancis/imgproxy)[![Total Downloads](https://camo.githubusercontent.com/e56bd842a55ed2cdf871bc58917290ac3717c4ac30be2e1bc6ca35b45266203c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6161726f6e6672616e6369732f696d6770726f78792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aaronfrancis/imgproxy)[![GitHub Tests Action Status](https://camo.githubusercontent.com/d5acff391afdef46de645d0859cd79b8ef2ea385a2aee9920d0f442c3c9cd6de/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6161726f6e646672616e6369732f696d6167652d70726f78792f74657374732e79616d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/aarondfrancis/image-proxy/actions?query=workflow%3Atests+branch%3Amain)[![License](https://camo.githubusercontent.com/8a5647e3a1be65347023a0425784d8c9fb7d88557b74447bb4714e0378e9d1be/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6161726f6e6672616e6369732f696d6770726f78792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aaronfrancis/imgproxy)

On-the-fly image resizing and format conversion for Laravel. Transform images via URL parameters—no pre-processing, no cache bloat, just simple URLs that your CDN can cache.

```

```

Upload once, serve any size. Let Cloudflare (or any CDN) cache the results at the edge.

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

[](#installation)

```
composer require aaronfrancis/imgproxy
```

Publish the config file:

```
php artisan vendor:publish --tag=imgproxy-config
```

Usage
-----

[](#usage)

The package automatically registers a route for image proxying:

```
/{options}/{source}/{path}

```

- `{options}` — comma-separated key=value pairs (e.g., `w=400,f=webp`)
- `{source}` — configured source name (validated against your config)
- `{path}` — path to the image, can include subdirectories

### Options

[](#options)

OptionAliasDescriptionExample`width``w`Target width in pixels`w=400``height``h`Target height in pixels`h=300``fit`Resize mode (see below)`fit=cover``quality``q`JPEG/WebP quality (1-100)`q=80``format``f`Output format (jpg, png, gif, webp)`f=webp``v`Cache buster (ignored, see below)`v=2`### Fit Modes

[](#fit-modes)

ModeDescription`scaledown`Scale to fit within dimensions, never enlarge (default)`scale`Scale to fit within dimensions, may enlarge`cover`Crop to fill exact dimensions (center crop)`contain`Fit inside dimensions with padding`crop`Crop from center to exact dimensions### Cache Busting

[](#cache-busting)

Use the `v` option to bust browser and CDN caches when an image changes. The value is ignored by the proxy but creates a unique URL:

```

```

Since the URL changes, browsers and CDNs will fetch the new version. Increment `v` each time the source image is updated.

### Examples

[](#examples)

```

```

URL Builder
-----------

[](#url-builder)

Use the fluent `imgproxy()` helper to generate URLs in your PHP code:

```
// Basic usage
imgproxy('images', 'photo.jpg')->width(400)
// => /w=400/images/photo.jpg

// Chain multiple options
imgproxy('images', 'photo.jpg')
    ->width(800)
    ->height(600)
    ->fit('cover')
    ->quality(85)
    ->webp()
// => /w=800,h=600,fit=cover,q=85,f=webp/images/photo.jpg

// Cache busting
imgproxy('images', 'photo.jpg')->width(400)->v(2)
// => /w=400,v=2/images/photo.jpg
```

The builder implements `Stringable` and `Htmlable`, so you can use it directly in Blade:

```

```

### Available Methods

[](#available-methods)

MethodAliasDescription`width(int)``w()`Set width in pixels`height(int)``h()`Set height in pixels`quality(int)``q()`Set quality (1-100)`format(string)``f()`Set output format`fit(string)`Set fit mode`version(string)``v()`Cache buster`webp()`Shortcut for `format('webp')``png()`Shortcut for `format('png')``jpg()`Shortcut for `format('jpg')``gif()`Shortcut for `format('gif')``cover()`Shortcut for `fit('cover')``contain()`Shortcut for `fit('contain')``scale()`Shortcut for `fit('scale')``scaleDown()`Shortcut for `fit('scaledown')``crop()`Shortcut for `fit('crop')``url()`Get the URL stringConfiguration
-------------

[](#configuration)

### Sources

[](#sources)

Configure image sources in `config/imgproxy.php`. Each source maps a URL prefix to a Laravel filesystem disk:

```
'sources' => [
    // /w=800/images/photo.jpg serves photo.jpg from 'public' disk
    'images' => [
        'disk' => 'public',
    ],

    // /w=800/uploads/photo.jpg serves from 'public' disk's uploads/ directory
    'uploads' => [
        'disk' => 'public',
        'root' => 'uploads',  // prepended to all paths
    ],

    // /w=800/media/photo.jpg serves from 's3' disk with validation
    'media' => [
        'disk' => 's3',
        'validator' => PathValidator::extensions(['jpg', 'png', 'webp']),
    ],
],
```

Source options:

OptionDescription`disk`Laravel filesystem disk name`root`Directory prepended to all paths (optional)`validator`PathValidator or custom class for path validationThe `root` option is useful when you want a short URL prefix but files are stored in a subdirectory. For example, with `'root' => 'uploads'`, a request to `/w=400/media/photo.jpg` loads `uploads/photo.jpg` from the disk.

Unknown sources return 404 at the routing level.

### Path Validation

[](#path-validation)

Restrict which paths can be served using the built-in validators:

```
use AaronFrancis\ImgProxy\PathValidator;

// Only allow paths in specific directories
PathValidator::directories(['images', 'uploads'])

// Only allow paths matching glob patterns
PathValidator::matches(['**/*.jpg', '**/*.png'])

// Only allow certain extensions
PathValidator::extensions(['jpg', 'png', 'webp'])

// Chain them in any order
PathValidator::directories(['uploads'])->extensions(['jpg', 'png'])
PathValidator::extensions(['jpg', 'png'])->directories(['uploads'])
```

Pattern syntax for `matches()`:

- `*` matches any characters except `/`
- `**` matches any characters including `/`
- `?` matches a single character

The validator receives the full path including the `root` prefix, so you can validate the complete filesystem path.

For custom validation, implement `PathValidatorContract`:

```
use AaronFrancis\ImgProxy\Contracts\PathValidatorContract;

class MyValidator implements PathValidatorContract
{
    public function validate(string $path): bool
    {
        // Your validation logic
        return true;
    }
}

// In config
'validator' => MyValidator::class,
```

### Maximum Dimensions

[](#maximum-dimensions)

Hard caps to prevent abuse:

```
'max_width' => 2000,
'max_height' => 2000,
```

### Allowed Formats

[](#allowed-formats)

Restrict which output formats can be requested:

```
'allowed_formats' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
```

### Default Quality

[](#default-quality)

Set the default quality for JPEG and WebP when not specified in the URL:

```
'default_quality' => 85,
```

### Cache Headers

[](#cache-headers)

Configure the cache headers sent with responses:

```
'cache' => [
    'max_age' => 2592000,              // 30 days browser cache
    's_maxage' => 2592000,             // 30 days CDN cache
    'stale_while_revalidate' => 86400, // Serve stale for 1 day while revalidating
    'stale_if_error' => 86400,         // Serve stale for 1 day if origin errors
    'immutable' => true,
],
```

- `stale_while_revalidate` — When cache expires, CDN serves stale content while fetching fresh in background
- `stale_if_error` — If origin is unavailable, CDN continues serving stale content instead of errors

### Rate Limiting

[](#rate-limiting)

Limits requests per IP per image path (prevents abuse by requesting many resize variations). Enabled by default in production:

```
'rate_limit' => [
    'enabled' => true,
    'max_attempts' => 10,  // per minute
],
```

Most images should be cached by your CDN, so legitimate users will rarely hit your origin server at all. This limit is a safety net against bad actors.

### Route Configuration

[](#route-configuration)

Customize the route prefix, middleware, and name:

```
'route' => [
    'enabled' => true,
    // By default this is null, so it serves from root: /{options}/{source}/{path}
    // Add a prefix (e.g. "transform") to serve from a path: /transform/{options}/{source}/{path}
    'prefix' => null,
    'middleware' => [
        // Ensure your middleware don't start sessions or include cookies! This will prevent caching.
    ],
    'name' => 'imgproxy.show',
],
```

Avoid middleware that starts sessions or sets cookies—these prevent CDN caching.

Set a prefix if you prefer URLs like `/img/{options}/{source}/{path}`:

```
'prefix' => 'img',
```

### Custom Route

[](#custom-route)

Disable the default route and register your own:

```
// config/imgproxy.php
'route' => [
    'enabled' => false,
],

// routes/web.php
use AaronFrancis\ImgProxy\Http\Controllers\ImgProxyController;

Route::get('{options}/{source}/{path}', [ImgProxyController::class, 'show'])
    ->where('options', '([a-zA-Z]+=[a-zA-Z0-9]+,?)+')
    ->whereIn('source', array_keys(config('imgproxy.sources')))
    ->where('path', '.+\.[a-zA-Z0-9]+')
    ->name('imgproxy.show');
```

Why No Server-Side Cache?
-------------------------

[](#why-no-server-side-cache)

This package intentionally does not cache processed images on the server. The entire point of this architecture is to let your CDN cache the processed images at the edge. Configure your CDN to respect the `Cache-Control` headers (30 days by default) and you get global caching for free.

**Recommended setup**: Put Cloudflare, Fastly, or any CDN in front of your app. The first request processes the image, subsequent requests are served from CDN cache.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 10, 11, or 12
- Intervention Image 3.x

License
-------

[](#license)

MIT

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance74

Regular maintenance activity

Popularity11

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 97.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

Unknown

Total

1

Last Release

141d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/033238953a59b9223a1bde703b5e4254e63c7412195da1cb9de5af44bf53fc0a?d=identicon)[aarondfrancis](/maintainers/aarondfrancis)

---

Top Contributors

[![aarondfrancis](https://avatars.githubusercontent.com/u/881931?v=4)](https://github.com/aarondfrancis "aarondfrancis (45 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

laravelproxyimageresizeoptimization

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/aaronfrancis-imgproxy/health.svg)

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

###  Alternatives

[intervention/image-laravel

Laravel Integration of Intervention Image

1496.5M102](/packages/intervention-image-laravel)[bkwld/croppa

Image thumbnail creation through specially formatted URLs for Laravel

510496.0k23](/packages/bkwld-croppa)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

71510.9M66](/packages/laravel-mcp)[joshembling/image-optimizer

Optimize your Filament images before they reach your database.

111145.4k12](/packages/joshembling-image-optimizer)[galahad/laravel-addressing

Laravel package providing addressing functionality

70316.6k](/packages/galahad-laravel-addressing)[ace-of-aces/laravel-image-transform-url

Easy, URL-based image transformations inspired by Cloudflare Images.

1756.4k](/packages/ace-of-aces-laravel-image-transform-url)

PHPackages © 2026

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