# imgproxy: image processing as a URL your application builds

> A Go server that takes a source image URL plus processing options in the request path, resizes and converts the result on demand, and deliberately leaves a few jobs to the CDN in front of it.

**imgproxy/imgproxy** — Fast and secure standalone server for resizing, processing, and converting images on the fly

- Repository: https://github.com/imgproxy/imgproxy
- Website: https://imgproxy.net
- Stars: 11,139 · Forks: 780
- Language: Go
- License: Apache-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/imgproxy-imgproxy

## The processing options live in the request path

imgproxy replaces whatever image handling code sits inside a web application. Instead of a controller that opens an image, resizes it with a library, writes a temporary file and streams it back, your application builds a URL. You hand the server a source image address and a set of processing options encoded in the path, and it returns the processed image. The result plugs into HTML, CSS or JavaScript the same way any other image URL does, which means a CDN can sit in front of it without special handling.

That design has a direct consequence for application code. The README is blunt about it: the only thing your application has to do is generate imgproxy URLs with the processing options you want. There is no template step, no manifest of variants to keep in sync, and no job queue. The README frames this as the answer to repeatedly re-preparing images each time a design changes, since the transformation is recomputed per request rather than baked into an asset you have to regenerate.

The repository layout shows where that work happens. `fetcher/` retrieves the source, `imagetype/`, `imagemeta/` and `imagedata/` deal with format and dimensions, `imath/` holds image math helpers, and `options/` parses the processing options out of the URL. `handlers/` is the HTTP surface and `imgproxy.go` and `init.go` sit at the top level as the entry points. `privatenet/` and `bufreader/` suggest careful handling of upstream connections and buffered reads, which is the sort of detail that matters when the server is fetching images from URLs it did not choose.

The README also points to an introduction article by Evil Martians for the design rationale, which is worth reading if you are weighing imgproxy against doing the work in-process.

## libvips does the pixels, and HTTPS is somebody else's job

The speed story starts with the image processing library. imgproxy builds on libvips and the README describes the tuning around it in plain terms, with a benchmark report linked for comparison against other image processing servers. There is also a `BENCHMARK.md` at the repository root, so the project keeps its own numbers in the tree rather than only on the website.

The simplicity principle is more interesting, because it shows up as a refusal. imgproxy does not implement HTTPS. The reasoning in the README is that in production the server lives behind a CDN, a load balancer or a reverse proxy, all of which terminate TLS already, so a second implementation inside imgproxy would be code nobody benefits from. The same logic rules out rounded corners and masks, which the README pushes to CSS on the grounds that CSS does it more easily and more flexibly. The stated rule is that if something can be done better outside imgproxy, the wheel is not reinvented.

That is a coherent position, and it is worth checking against your own deployment. If you run imgproxy on a private network with no proxy in front of it, you are the one terminating TLS, and this feature list will not help you. The `heroku/` and `docker/` directories, plus `app.json` and `heroku.yml` at the root, indicate that the packaged deployments assume a platform that handles ingress.

Configuration is a single Go file at the root, `config.go`, which reads from the environment. The release history shows how carefully that mapping is maintained: v4.0.13 fixed inconsistent environment variable names between the code and the documentation, naming `IMGPROXY_AIRBRAKE_ENVIRONMENT`, `IMGPROXY_S3_USE_DECRYPTION_CLIENT`, `IMGPROXY_USE_LAST_MODIFIED` and `IMGPROXY_USE_ETAG`, and also fixed `IMGPROXY_ENABLE_CLIENT_HINTS` never being parsed from the environment at all.

## Signed URLs and the image bomb problem

Image processing is a wide attack surface, and the README treats it as one. Four protections are listed, and each addresses a specific way a public image endpoint gets abused.

URL signing is the first. Without it, anyone can point your server at arbitrary images and use your CPU and bandwidth, or simply use your server as an attacker's infrastructure. The second is a type check before the download completes, so a request for something that is not an image does not cost you the full transfer. The third is the more interesting one: imgproxy reads the real image dimensions before decoding, which is what stops decompression bombs of the kind described in the linked security research. A small file can expand to gigabytes of pixels in memory, and a dimension check before decode is the cheap way to reject it.

The fourth is authorization by HTTP header, which exists to stop direct access that bypasses the CDN or caching layer in front of imgproxy. Together these are the configuration surface to review before going live.

Signing is also the part of imgproxy that pushes work into your codebase, and the repository is unusually helpful about it. `examples/` holds eighteen reference implementations of the signature algorithm, one per language: Go, Java, JavaScript, Python, Ruby, Rust, PHP, C#, Dart, Swift, Clojure and Elixir are all there, plus variants for a truncated signature in `.mjs` and `.php`, an encrypted source URL in Go, JavaScript and Ruby, and a CloudFront function written in JavaScript. If your application constructs image URLs on the server in one language and renders them from a browser in another, both sides need the algorithm and the examples cover both cases.

## What the Apache-2.0 build leaves to the commercial tier

The README carries a four-row table dividing imgproxy OSS from imgproxy Pro, and the split is informative about where the project's effort goes.

Format support in the free version covers the basics: JPEG, PNG, GIF, WebP, AVIF and JPEG XL, with a documentation page for the full list. Preview generation for video, PDF and Photoshop documents is in Pro. Processing in OSS is resizing, cropping, rotating, watermarking and filters, while Pro adds image info retrieval, advanced watermarking and colour adjustment. Optimization in OSS is colour profile and metadata stripping plus PNG quantization; Pro adds advanced compression settings, GIF to MP4 conversion and SVG minification.

The smart features row is the widest gap. The free build does simple smart cropping and auto-quality by file size. Pro adds object detection, advanced smart cropping, auto-quality scored by SSIM, and best format selection. In practice that means automatic format negotiation and content-aware cropping are commercial, and the free version's two smart features are the simpler heuristics.

The practical reading is that a straightforward thumbnail and format pipeline is fully covered by the open source build. Anything that needs to pick a format per request or crop around a detected subject is the upgrade trigger. The project is licensed Apache-2.0 with a `LICENSE` and `NOTICE` at the root, has 11,085 stars and 776 forks, and the last push was on 2026-09-15, with v4.0.15 released on 2026-09-14.

## The dependency list is the real deployment story

`go.mod` is more informative about what imgproxy can talk to than any paragraph in the README. The module is `github.com/imgproxy/imgproxy/v4` and it requires Go 1.27.0. Storage support spans AWS, Azure and Google Cloud: the AWS SDK v2 appears with separate modules for S3, KMS, Secrets Manager, SSM, STS and CloudWatch, Azure contributes its core, identity and blob modules, and Google contributes storage and secret manager.

The observability list is just as wide. Datadog, Sentry, New Relic, Airbrake, Bugsnag and Honeybadger each get an integration, and OpenTelemetry bridges appear alongside them. Prometheus is there through `client_golang`, and `gopsutil` covers system metrics. `monitoring/` and `errorreport/` at the repository root are where that wiring lives.

A few smaller entries are telling. `github.com/ncw/swift/v2` is a pure Go S3 implementation, which explains how S3 works without the AWS SDK being mandatory. `github.com/urfave/cli/v3` backs the `cli/` package. `github.com/matoous/go-nanoid/v2` is a nanoid generator, and `github.com/DarthSim/godotenv` reads a `.env` file, which is how you develop locally against a real config. `github.com/fsouza/fake-gcs-server` and `github.com/johannesboyne/gofakes3` are test doubles for the two cloud backends, which is a sign the storage layer is tested against fakes rather than against real services.

The cost of that breadth is a binary that links a large dependency tree, even when you use one backend. The remaining development tooling in the tree, `.golangci.yml`, `lefthook.yml`, `.grype.yaml`, `lychee.toml` for link checking and a `k6/` directory for load testing, suggests the project treats both static analysis and request throughput as part of the definition of done.

## Recent releases are mostly correctness fixes

The three most recent releases are small and specific, which tells you something about the project's current shape. v4.0.15, published 2026-09-14, restored a documented behaviour that had regressed during the 4.x configuration rewrite: `IMGPROXY_GRACEFUL_STOP_TIMEOUT` once again defaults to twice `IMGPROXY_TIMEOUT` instead of a static 20 seconds. The same release fixed a panic that occurred while streaming a 304 Not Modified response that carried a body, and a Pro-only fix for EXIF extraction from DC RAW images.

v4.0.14, published 2026-08-24, fixed a panic on certain malformed request paths, with a trailing double slash given as the example, where the server returned a 500 instead of a proper 4xx response. That is a small change with a disproportionate lesson in it: image URLs are assembled by string concatenation in application code, so malformed paths reach a server that is publicly exposed and must not panic.

v4.0.13, published 2026-08-18, is the environment variable consistency pass described earlier, plus a fix for recovered non-error panics being logged as `panic: <nil>` rather than the actual value.

Two structural notes complete the picture. There is a `SECURITY.md` at the root, which is the file to read before exposing the service. And there is a `docs/` directory in the tree alongside the documentation site at docs.imgproxy.net, so configuration details beyond the README are in the repository as well. The README itself is an overview with links; the environment variable reference is not in it.

## Conclusion

imgproxy is at its best when image variants multiply faster than you can pre-generate files: the processing happens on request, the URL is the API, and the free version covers the resize, crop, rotate, watermark and format work most applications need. Two things to weigh before adopting it are that URL signing must be implemented in every client that constructs an image URL, since the repository ships eighteen reference implementations for exactly that, and that document previews, object detection and GIF to MP4 conversion sit behind the commercial tier rather than the Apache-2.0 build. Start with the OSS binary behind your existing reverse proxy, and read the security configuration in the docs rather than the README, since the README lists the protections without showing the environment variables that turn them on.

## FAQ

### What is an image proxy?

An image proxy is a service that stands between your application and its image files. It accepts a source image address plus a set of processing options, fetches the original, applies the transformation and returns the result, usually over plain HTTP so a CDN can cache it. imgproxy is one implementation of that pattern, where the processing options are encoded directly in the request URL.

### How do you stop imgproxy from being used as a free image service by strangers?

Sign the URLs. imgproxy supports URL signing so that only requests carrying a valid signature for the exact source and options are processed, which prevents someone else spending your CPU and bandwidth on their own images. The repository ships eighteen reference implementations of the signature algorithm under `examples/`, one per language, plus a CloudFront function variant for edge signing.

### Does imgproxy handle HTTPS itself?

No, by deliberate choice. The README explains that imgproxy is expected to run behind a CDN, load balancer or reverse proxy in production, all of which terminate TLS, so implementing HTTPS inside imgproxy would be code nobody benefits from. If you intend to expose it directly without a proxy in front, you have to terminate TLS yourself.

### What is the difference between imgproxy OSS and imgproxy Pro?

The free Apache-2.0 build covers the common path: resizing, cropping, rotating, watermarking and filters, plus JPEG, PNG, GIF, WebP, AVIF and JPEG XL support, colour profile and metadata stripping, PNG quantization, simple smart cropping and auto-quality by file size. Pro adds video, PDF and Photoshop previews, object detection, advanced smart cropping, auto-quality scored by SSIM, best format selection, GIF to MP4 conversion and SVG minification.

## Sources

- [imgproxy/imgproxy on GitHub](https://github.com/imgproxy/imgproxy)
- [License: Apache-2.0](https://github.com/imgproxy/imgproxy/blob/master/LICENSE)
- [Project website](https://imgproxy.net)
- [README](https://github.com/imgproxy/imgproxy/blob/master/README.md)
- [Releases](https://github.com/imgproxy/imgproxy/releases)

---

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