You get a resized, cropped, or converted image by requesting a URL that lists the processing options before the image's path:
https://img.example.com/w=400/h=300/fit=cover/src/photos/beach.jpgRequesting images from an ImagePipe server takes a few details from its configuration:
- The base URL, such as
https://img.example.comorhttps://example.com/images. - What an image path looks like: a path such as
photos/beach.jpg, or a full URL when the images come from another website. - The names of any presets defined in the server's configuration, and what each one does.
- Whether URLs must be signed, and how you get signed URLs.
URL structure
https://img.example.com/w=400/h=300/fit=cover/src/photos/beach.jpg
└───── base URL ──────┘└────── options ──────┘ └─ image path ─┘Each option is one path segment, written name=value, such as w=400.
An on/off option is written by its name alone, such as enlarge. Values are
described under option values.
The options end at src/, and everything after it is the image path. A URL
with no options, such as https://img.example.com/src/photos/beach.jpg, is
valid too. ImagePipe then only chooses the output format.
ImagePipe rejects a URL with 400 when it has an unknown option, the same
option twice in one group, options that conflict, or an option that has no
effect, such as fit=cover without a width or height (w, h, min-w, or
min-h). It also rejects:
- A query string, such as
?v=2. To get a fresh copy after an image changes, use thecboption instead. - Percent escapes, such as
%20, anywhere in the options. - Empty segments (
//) and the segments.and..in the options. - More than 64 option segments.
Image paths
URL-encode the image path, keeping its slashes:
summer photos/beach #1.jpg becomes src/summer%20photos/beach%20%231.jpg,
and the full URL https://assets.example.com/a.jpg?v=2 becomes
src/https://assets.example.com/a.jpg%3Fv=2.
The server holding the image receives a full URL's path unchanged, so
https://assets.example.com/w_100,h_100/a+b.jpg keeps its , and +. To
send an escape such as %2B, URL-encode its % too:
src/https://assets.example.com/a%252Bb.jpg requests /a%2Bb.jpg.
Two other markers can take the place of src/:
src64/followed by the image path in unpadded base64url, for examplesrc64/cGhvdG9zL2JlYWNoLmpwZwforphotos/beach.jpg. Leave out the trailing=characters.enc/followed by an encrypted token that hides the image path. These tokens need the server's encryption key, so they are created server-side, for example by the application that builds your URLs. A token that no server key decrypts answers404. A server without source encryption keys answers400for everyenc/path.
Processing groups
The options between two - segments form a group. Within a group, the order
you write options in doesn't matter: ImagePipe always applies them in a
fixed order, so w=500/trim=fff and
trim=fff/w=500 both trim first, then resize.
A - starts a new group, which processes the result of the previous one.
This URL resizes the image to 500 pixels wide, then trims the white border
from the smaller image:
URL
/w=500/-/trim=fff/src/photos/beach.jpgElixir
ImagePipe.URL.new()
|> ImagePipe.URL.group(resize: [width: 500])
|> ImagePipe.URL.group(trim: "fff")Each group starts with fresh settings. A dpr=2 in the first group doesn't
apply to the second.
Request-wide options apply to the whole request rather than to one group:
the output and encoding options, the
request controls, orient, and page. You can write
each one anywhere in the URL, but only once. A group that holds only
request-wide options adds no group, so /w=800/-/format=webp is the same request as
/w=800/format=webp.
A URL must not start or end with -, or contain two - segments in a row.
Processing order and groups explains the order and
when a new group helps.
Option values
Numbers
Plain decimals: 2, 1.5, -10. Write at least one digit before and after
the point (0.5, not .5), and no + or exponent. Each option states its
range.
Pixel lengths
A plain number is a length in pixels: w=400. Don't add a unit, since
400px is rejected. Widths and heights (w, h, min-w, min-h) take
whole numbers, and w and h also accept auto. Crop sizes, regions, and
offsets accept decimals, and offsets may be negative.
Pixel lengths have an absolute value of at most 2147483647.
pad has its own lower maximum.
URL
crop=400,300Elixir
ImagePipe.URL.group(builder, crop: {400, 300})Percentages
A number followed by pct is a percentage: 50pct. The % sign can't be
used. Crop sizes, regions, and offsets accept percentages. Each option page
says what the percentage is of.
Percentage values have an absolute value of at most 2147483647.
URL
crop=50pct,100pctElixir
ImagePipe.URL.group(builder, crop: {{:pct, 50}, {:pct, 100}})Fractions
A decimal from 0 to 1, inclusive. Focus points, opacity, and alpha use
fractions: focus=0.3,0.6 sets a crop target 30% from the left and 60% from
the top.
Colors
A color is three or six hex digits without #, such as fff or ff8800,
or a lowercase CSS color name, such as white or rebeccapurple. Some
options take an alpha fraction after the color: bg=fff,0.5
is half-transparent white. The CSS name transparent fails with 400. To
drop a background that a preset sets, use
bg=unset.
URL
bg=ff8800
bg=fff,0.5Elixir
ImagePipe.URL.group(builder, background: "ff8800")
ImagePipe.URL.group(builder, background: {"fff", 0.5})Anchors
A position in the image: center, top, bottom, left, right,
top-left, top-right, bottom-left, or bottom-right. The anchor
option also accepts smart and smart-face, described under
crop guides.
Booleans
Write the option's name alone for true and =false for false: enlarge
or enlarge=false. enlarge=true is rejected. =false turns off something
a preset turned on.
URL
enlarge
enlarge=falseElixir
ImagePipe.URL.group(builder, resize: [enlarge: true])
ImagePipe.URL.group(builder, resize: [enlarge: false])Named values
Lowercase names, with hyphens between words: anchor=top-left, flip=hv,
format=webp. Each option page lists the names it accepts.
URL
anchor=top-leftElixir
ImagePipe.URL.group(builder, anchor: :top_left)Pairs and lists
Several values in one option are separated by commas, without spaces:
crop=400,300 is a width and a height, zoom=2,1 an x and a y factor.
Each option page says how many values it takes. Ratios use a colon or a
decimal: crop-ratio=16:9 or crop-ratio=1.5.
After reduction to whole-number terms, each term must be at most 2147483647.
Named presets
A preset is a named set of options defined in the server's configuration.
Write preset= and the name where you would write the options:
/preset=card/src/photos/beach.jpgYou can combine a preset with your own options. Options you write yourself
win over the preset's options in the same group, so with a card preset of
w=400/h=300/fit=cover, this URL is 600 pixels wide:
/preset=card/w=600/src/photos/beach.jpgpreset=card,darkapplies both presets. When they set the same option, the later one wins.- A preset applies to the group you write it in.
/w=800/-/preset=frameappliesframeto the resized image. - A preset's request-wide options, such as
format, apply to the whole request. Aformatyou write yourself wins over every preset. - Some options replace a related set rather than one value. Writing
anchor,focus, ordetectreplaces the preset's whole crop target,regionreplaces itscrop,qreplaces itsautoqualityandformat-q, andwmreplaces its watermark. Aformat-qin your own URL still wins over yourqfor the formats it lists. format-qand the encoder options combine field by field. Yourjpeg-options=quant-table:3keeps a preset'sprogressive, and a field set in both takes your value.unsetremoves a preset's value as if it had never been set:/preset=brand/wm=unsetremoves the watermark. Every option exceptpresetacceptsunset. Informat-qand the encoder options,unsetcan come first:jpeg-options=unset,progressivedrops the preset's JPEG settings, then turns onprogressive.
The server's configuration can also set defaults for the first group of every
request. Presets and your own options win over them, and unset removes them
too.
A preset can also define several groups of its own. You can add only
request-wide options to such a preset, such as /preset=framed/format=png,
either directly or through another preset. Adding any other option answers
400. The server's configuration defines which presets work this way, as
described in single-group and pipeline presets.
A preset name that doesn't exist answers 400.
Signed URLs
When ImagePipe requires signed URLs, each URL starts with a sig= segment
that covers everything after it:
https://img.example.com/sig=<signature>/w=400/src/photos/beach.jpgSigning needs the server's secret key, so URLs are signed server-side. The application that builds your URLs signs them, or an endpoint in it creates signed URLs. Signing is set up as described in signing URLs and rotating keys.
- Changing any option or the image path invalidates the signature.
- A missing or wrong signature answers
403with the bodyinvalid signature. - A signed URL may carry
expires=with a Unix time in seconds. After that second, the URL answers410with the bodyexpired. - When ImagePipe doesn't require signatures, a URL with a
sig=segment answers400.
Output formats
Without a format option, ImagePipe picks AVIF or WebP when the browser's
Accept header lists it. Otherwise JPEG and PNG originals keep their format,
and any other format becomes PNG if the image has transparency, JPEG if not. With
format=webp (or avif, jpeg, png) you always get that format. See
formats for the details.
Ignored options
An option that has no effect where it is written is ignored, and the request
is served as if the URL left it out. /fit=cover/src/photos/beach.jpg has no
width or height for fit to use, so it serves the same image as
/src/photos/beach.jpg and shares its cached copy. Each option's reference
says what it needs.
With the debug option, on a server that
allows debug headers, the response lists the ignored options in
X-ImagePipe-Ignored-Options. Options that a preset or the server's defaults
supply are ignored without being listed.
When a request fails with 400 for another reason, the
error body marks the ignored options as well, with messages
such as ignored: crop-ratio requires crop.
Options that contradict each other, such as crop and region in one group,
still fail with 400.
Request errors
A request that fails answers with a status and a short plain-text body. For a
400, the body points at each problem in the URL:
invalid transformation options
/w=400/fit=fill/src/photos/beach.jpg
^^^^
|
invalid value: expected contain, cover, stretch, or auto| Status | Meaning |
|---|---|
400 | The URL doesn't parse, or its options don't fit together. |
403 | The signature is missing or wrong. |
404 | The image doesn't exist, or an enc/ token can't be decrypted. |
410 | The URL's expires time has passed. |
Error responses lists every status, including those for images that are too large or can't be processed.
Next steps
- Processing options: every option, grouped by category.
- Resize and layout: width, height, fit, and pixel density, the options most requests start with.
- Request controls: downloads, file names, and cache busting.