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(6mo ago)223MITPHPPHP ^8.2CI passing

Since Dec 28Pushed 6mo agoCompare

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

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

32

—

LowBetter than 69% of packages

Maintenance68

Regular maintenance activity

Popularity9

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

187d 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

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M151](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58171.4k14](/packages/api-platform-laravel)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M146](/packages/laravel-cashier)[intervention/image-laravel

Laravel Integration of Intervention Image

1588.9M182](/packages/intervention-image-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)

PHPackages © 2026

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