Format & Quality
A stored JPEG does not have to leave as a JPEG. The same download URL that resizes can also transcode, and by default it does so on its own — a modern browser gets AVIF from a PNG original without anyone asking.
Explicit Format
GET /api/buckets/photos/files/{key}?format=webp
| Value | Output | Use it for |
|---|---|---|
avif |
image/avif |
Smallest payload. Broad but not universal support. |
webp |
image/webp |
Strong compression, effectively universal today. |
jpeg |
image/jpeg |
Photos where nothing may be assumed about the client. |
png |
image/png |
Transparency and lossless output. |
origin |
source | Opt out of transcoding for this request. |
The response Content-Type always reflects what was actually produced. An unrecognised value — bmp, tiff — answers 400.
Automatic Negotiation
Omit format and the server reads the request's Accept header:
GET /api/buckets/photos/files/{key}
Accept: image/avif,image/webp,image/*
Accept contains |
Output |
|---|---|
image/avif |
AVIF |
image/webp |
WebP |
| Neither | The original bytes, untouched |
AVIF wins over WebP when both are offered. This is why an ordinary <img src> with no query string still gets a modern format in a modern browser and the untouched original in an old one — no <picture> element, no srcset juggling, no server-side user-agent sniffing.
format=origin is the way to bypass negotiation deliberately: use it when a downstream consumer needs the exact stored bytes, or when you are debugging what was actually uploaded.
ECO_IMAGE_FORMAT does not govern this route. That env var sets the default output of the file.transformImage automation action. URL transforms negotiate from Accept and honour an explicit format — nothing else. Setting ECO_IMAGE_FORMAT=jpeg will not stop a browser advertising AVIF from receiving AVIF here.
Quality
GET /api/buckets/photos/files/{key}?quality=95
GET /api/buckets/photos/files/{key}?width=100&quality=30
| Behaviour | Detail |
|---|---|
| Accepted range | Integer, 1 to 100 inclusive. |
| Default | 80 when omitted. |
| Applies to | Lossy output — JPEG, WebP, AVIF. |
| Ignored for | PNG, which is lossless. |
| Outside the range, or non-integer | 400 |
Eighty is not a placeholder — it is close to the point where further quality stops being visible and starts only being bytes. Raising it to 95 can double the payload for a difference most viewers will not see on most images.
The pairing worth remembering is width with a low quality. A 100-pixel-wide thumbnail at quality=30 is a fraction of a full-quality one and looks identical at that size, because compression artefacts are themselves scaled away. Reserve high quality for images that will be viewed large.
Choosing in Practice
Three defaults that cover almost every case:
- Content images in a page — no
formatat all. Let negotiation do it; you get AVIF where it helps and correctness everywhere else. - Thumbnails and avatars —
?width=…&quality=60. The size does the work; quality is nearly free to lower. - Downloads a user asked for —
?format=origin. Someone clicking "download original" means it.
Related Pages
- Resize & Crop — dimensions, fit modes, crop strategies.
- Presets & Caching — bundling these parameters under a name.
- File Operations — the endpoint being decorated.
- Ecoconception — where
ECO_IMAGE_FORMATdoes apply. - Environment Variables: Services — the
ECO_*reference.
Last updated July 27, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.