Image Optimizer reference

The Fastly Image Optimizer (IO) manipulates and transforms images as they pass through the Fastly network, and caches optimized versions of them.

IO shielding illustration

IO interacts with the fetch node in the shield POP (see clustering and shielding). IO-enabled requests that ultimately load an image from origin will transit the shield fetch node twice. This results in both the original and the transformed image being cached at the shield, while just the transformed image will be cached at the edge.

IMPORTANT: If using custom VCL, be aware that at the shield POP, VCL subroutines that normally run on a fetch node (vcl_miss, vcl_pass, and vcl_fetch) will run after passing through the image optimizer. As a result, these subroutines handle the request for the original image, while all other VCL subroutines on the shield POP (and all subroutines on the edge POP) are part of the request for the transformed image.

Enabling image optimization

By default, Fastly services do not have access to image optimization. To enable it, contact sales and include the service ID of the service for which IO should be enabled. Once enabled, you can trigger Fastly to pass a request through the image optimizer by adding the x-fastly-imageopto-api header in vcl_recv. This is usually done conditionally, so that it applies only to image requests:

sub vcl_recv { ... }
Fastly VCL
if (req.url.ext ~ "(?i)^(gif|png|jpe?g|webp)$" || req.url.path ~ "^/images/") {
set req.http.x-fastly-imageopto-api = "fastly";
}

Services that use image optimization are required to enable shielding.

These steps can also be performed via the web interface.

Other options may also be specified in the x-fastly-imageopto-api header value. See caching below.

Default behavior

Enabling IO will activate a set of standard transformations and filters intended to provide 'good defaults' that will not change the image's size or visual fidelity. Many of these can be overridden or further customized by providing explicit configuration directives as query params or headers:

  • The quality of jpg, pjpg, or webp images will be set to the value specified in the IO web interface. The default value is 85%.
  • All metadata (for example, EXIF, XMP, or ICC) will be removed.
  • If the image contains an ICC profile, the data will be applied directly to the image to ensure color output is correct. If the image doesn't contain an ICC profile, a default profile is added.
  • If the source image contains orientation metadata, this orientation will be applied directly to the image data and metadata will be removed.

Configuration

Often the default transformations will save a significant amount of data without any further effort, but you can customize the behavior with query parameters and headers. For example, the following query string will direct the IO processor to resize the image to 300 pixels wide and crop it to a 16:9 ratio, centered on the most important visual content, including the detection of faces:

/image.png?width=300&crop=16:9,smart

Query parameters

We recognize the following parameters in the query string of the image request:

ParameterDescription
autoEnable optimization features automatically.
bg-colorSet the background color of an image.
blurSet the blurriness of the output image.
brightnessSet the brightness of the output image.
canvasIncrease the size of the canvas around an image.
contrastSet the contrast of the output image.
cropRemove pixels from an image.
disableDisable functionality that is enabled by default.
dprServe correctly sized images for devices that expose a device pixel ratio.
enableEnable functionality that is disabled by default.
fitSet how the image will fit within the size bounds provided.
formatSpecify the output format to convert the image to.
frameExtract the first frame from an animated image sequence.
heightResize the height of the image.
levelSpecify the level constraints when converting to video.
optimizeAutomatically apply optimal quality compression.
orientChange the cardinal orientation of the image.
padAdd pixels to the edge of an image.
precropRemove pixels from an image before any other transformations occur.
profileSpecify the profile class of application when converting to video.
qualityOptimize the image to the given compression level for lossy file formatted images.
resize-filterSpecify the resize filter used when resizing images.
saturationSet the saturation of the output image.
sharpenSet the sharpness of the output image.
trimRemove pixels from the edge of an image.
widthResize the width of the image.

Header parameters

HeaderDescription
x-fastly-imageopto-montageCombine up to four images into a single displayed image.
x-fastly-imageopto-overlayOverlay one image on top of another image.

Processing order

Although the parameters can be specified in any order, we normalize the transformation sequence within our system to the following order:

  1. precrop
  2. trim
  3. crop
  4. orient
  5. width height dpr fit resize-filter disable enable
  6. pad canvas bg-color
  7. brightness contrast saturation
  8. sharpen
  9. blur
  10. x-fastly-imageopto-overlay
  11. format auto optimize quality profile level

If an x-fastly-imageopto-montage header is specified, all other IO params and headers are ignored.

Caching

The original image is only requested and cached once, even if distinct requests might demand versions of the image that are transformed differently.

For example, a user on a desktop device triggers a request for image.png?width=1600, while a different user on a mobile device requests image.png?width=400. These requests are considered to be different for the purposes of caching transformed images and will result in different cache objects, but the request to origin is image.png (with no query params).

IMPORTANT: A request with image optimization enabled cannot make use of cached content created by a request that did not have image optimization enabled. Activating a configuration that enables IO on a large number of images may therefore result in a temporary, sharp decrease in cache hit ratio and corresponding increase in traffic to origin. See enabling features gradually if you need to avoid this.

Query string removal

By default, all query parameters are stripped, even those that are not recognized by the image optimizer. To allow passthrough of unknown query params, opt-in by changing the value of the X-Fastly-Imageopto-Api header:

set req.http.X-Fastly-Imageopto-Api = "fastly; qp=*";

With this opt-in enabled, a request for image.png?width=300&something=foo would trigger the original image to be loaded from your origin server with a request URI of image.png?something=foo. The known parameter has been removed, but the unknown parameter was passed through.

WARNING: Enabling the qp=* override may reduce the image cache hit ratio and increase traffic to your origin servers.

Purging images from the Fastly cache

The query string normalization described above happens prior to the vcl_hash subroutine and the IO query params are saved in a secondary hash to allow separation of the variants. This allows all variants of the same image to be purged in a single request.

To purge the original image and all variants, make a purge request without IO parameters:

$ curl -X PURGE https://example.com/image.jpg

It is not possible (and likely never desirable) to purge a single, transformed variant (because a subsequent request for that variant would produce the same result). It is also not possible to purge an original image without purging the transformed images, because subsequent requests would potentially result in caching an inconsistent set of images.

Testing and debugging

When images pass through the IO processor, it will add a header called fastly-io-info with the following form:

fastly-io-info: ifsz=108501 idim=827x788 ifmt=jpeg ofsz=13066 odim=300x286 ofmt=jpeg

This header provides detail on the input format (ifmt), dimensions (idim), and size in bytes (ifsz), and also the output format (ofmt), dimensions (odim), and size in bytes (ofsz).

Click 'RUN' on the interactive demo below to create an ephemeral Fastly service and make a request through it for an image of former US president Barack Obama.

In this demo, we also show how to calculate the size ratio between the original image and the transformed image by post processing the fastly-io-info header, dividing ofsz by ifsz, and multiplying by 100 to yield a percentage.

Errors and warnings

If an error occurs during image processing, a fastly-io-warning or fastly-io-error header is added to the response. The following error scenarios will prevent the image from being processed:

  • Image exceeds maximum dimensions
  • Image could not be parsed
  • Not a supported image format
  • Unsupported Content-Encoding
  • Gzipped body exceeds maximum length
  • Gzipped body could not be decoded
  • Invalid status
  • Response is pass
  • Response is not cacheable

Transformation classes

You may prefer not to expose image optimization parameters publicly. For example, allowing raw image transform parameters to be accepted on inbound client requests may allow an end users to gain access to a higher resolution of your source images than you had intended. Instead, consider implementing transform classes. In this example, we map some precomposed IO queries to general labels like "large", "medium", and "small", so that the image request from the client is ?class=large rather than ?crop=16:9,smart&width=640.

While not essential, the demo above also includes logic to remove any query params that are not the custom class param, preventing end-user customization of the IO behavior.

Using optimized images and videos in HTML

The Fastly Image Optimizer allows you to generate images to suit the way you want to lay them out on the client device, but it's up to you to prompt the client device to request the most appropriate image variant. If your client device is a web browser and you are serving HTML, then you can make use of responsive images web technologies.

Pixel density

Using the srcset attribute, it's possible to define images to be used at different display pixel densities, which works well with the width and dpr parameters.

<img srcset="https://www.fastly.io/image.jpg?width=320&dpr=1.5 1.5x,
https://www.fastly.io/image.jpg?width=320&dpr=2 2x"
src="https://www.fastly.io/image.jpg?width=320"/>

Art direction

Use the HTML5 <picture> element to deliver different image crops at different browser viewport sizes, a technique called art direction:

<picture>
<source srcset="https://www.fastly.io/image.jpg?width=600&crop=16:9" media="(min-width: 600px)"/>
<img src="https://www.fastly.io/image.jpg?width=320&crop=1:1"/>
</picture>

Image type

The <picture> element can also be used to provide different formats, allowing the browser to choose a format that best suits its needs and is compatible with the formats that it supports:

<picture>
<source type="image/webp" srcset="https://www.fastly.io/image.webp"/>
<source type="image/png" srcset="https://www.fastly.io/image.png"/>
<img src="https://www.fastly.io/image.jpg"/>
</picture>

Learn more about which image formats are supported in which browsers.

Replacing GIFs with inline video

The animated GIF format benefits from being universally compatible and plays inline on all major web browsers. However, with the introduction of the playsinline attribute, the <video> element is now usable in most of the same use cases as GIF. Video formats typically offer far better compression than GIF, and the Image Optimizer can be used to convert existing GIFs into MPEG 4 video:

<video width="300" height="224" playsinline autoplay muted loop>
<source src="https://www.fastly.io/image.gif?format=mp4" type="video/mp4" />
</video>

Limitations and constraints

  • The maximum input image file size is 50 Megabytes.
  • The maximum input image dimensions are 12,000 x 12,000 pixels.
  • The maximum output image dimensions are 8,192 x 8,192 pixels (8K Ultra HD).
  • The maximum number of frames an animated GIF can contain is 1,000.
  • We support input images in GIF, PNG, JPEG, or WEBP format.
  • We can produce output images in GIF, PNG, JPEG, WEBP, or MP4.