---
title: Image Optimizer reference
summary: null
url: https://www.fastly.com/documentation/reference/io
---


The Fastly [Image Optimizer](https://docs.fastly.com/products/image-optimizer) (IO) manipulates and transforms images as they pass through the Fastly network, and caches optimized versions of them.

![IO shielding illustration](/img/shield-illustration-precomposed.svg)

IO interacts with the *fetch node* in the *shield POP* (see [clustering](/guides/full-site-delivery/fastly-vcl/clustering-in-vcl) and [shielding](/guides/concepts/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 [upstream](/reference/glossary#term-upstream) (i.e., on the origin side) of 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

Image optimization is an optional upgrade to Fastly service plans. If you have not yet purchased IO, [contact sales](mailto:sales@fastly.com).

> **NOTE:** IO is available on Compute as part of Fastly's [Beta program](https://docs.fastly.com/products/fastly-product-lifecycle#beta). To use IO with Compute, [contact support](https://support.fastly.com/s/contactsupport).

If your Fastly account is entitled to use image optimization, it can be enabled on an individual service [in the web interface](/guides/full-site-delivery/image-optimization/using-fastly-image-optimizer/#enabling-and-disabling-the-fastly-image-optimizer) or by enabling the `image_optimizer` product using the [product enablement API](/reference/api/products/image_optimizer/).

<!-- TabbedPanels component: 
<Panel id="cdn-services">

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:

```vcl context="sub vcl_recv { ... }"
if (req.url.ext ~ "(?i)^(?:gif|png|jpe?g|webp|avif|jxl|heic)\z" || req.url.path ~ "^/images/") {
  set req.http.X-Fastly-Imageopto-Api = "fastly";
}
```

> **HINT:** Typically requests are flagged for IO processing using a path match as above, but if you prefer you can also [use the content-type of the response](/solutions/examples/io-response-content-type).

Services that use image optimization are required to enable [shielding](/guides/concepts/shielding/).

These steps can also be performed [via the web interface](/guides/full-site-delivery/image-optimization/about-fastly-image-optimizer/#setting-up-image-optimization).

Other options may also be specified in the `X-Fastly-Imageopto-Api` header value. See [caching](#caching) below.

> **WARNING:** IO will only process requests that are eligible for caching. See [limitations](#limitations-and-constraints).

</Panel>
<Panel id="compute-services">

> **IMPORTANT:** Image Optimizer is available on the Compute platform through our SDKs as part of Fastly's [Beta program](https://docs.fastly.com/products/fastly-product-lifecycle#beta). Any request sent to Image Optimizer, including through the SDK, counts as a [billable image request](https://docs.fastly.com/products/image-optimizer#billing) for the Image Optimizer product.

Once Image Optimizer is enabled for your Compute service, get started using our [SDKs](https://www.fastly.com/documentation/guides/compute/getting-started-with-compute/#choose-a-language-to-use).

<TabbedPanels syncGroup="languages">
<Panel id="rust">

The Image Optimizer Rust SDK documentation is available in our Rust [SDK reference](https://docs.rs/fastly/latest/fastly/image_optimizer/index.html).

```rust
use fastly::image_optimizer::{ImageOptimizerOptions, ImageOptimizerRegion};
use fastly::{Error, Request, Response};
use regex::Regex;

#[fastly::main]
fn main(mut req: Request) -> Result<Response, Error> {
    let image_regex = Regex::new(r"(?i)(?:gif|png|jpe?g|webp|avif|jxl|heic)\z").unwrap();
    let url_path = req.get_path();

    // Only images go to Image Optimizer using the regex above or assuming an images directory
    if url_path.contains("/images/") || image_regex.is_match(url_path) {
        let io_options = ImageOptimizerOptions::from_region(ImageOptimizerRegion::UsWest);
        req = req.with_image_optimizer(io_options);
        return Ok(req.send("origin")?);
    }

    // all other requests go to the normal path
    Ok(req.send("origin")?)
}
```

</Panel>

<Panel id="javascript">

The Image Optimizer JavaScript SDK documentation is available in our JavaScript [SDK reference](https://js-compute-reference-docs.edgecompute.app/docs/fastly:image-optimizer/imageOptimizerOptions).

```javascript


addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));

async function handleRequest(event) {
  // Define any default request options you want here
  const fetchOptions = {};

  const path = new URL(event.request.url).pathname;

  // Send image requests through Image Optimizer
  if (/\.(?:gif|png|jpe?g|webp|avif|jxl|heic)$/i.test(path)) {
    fetchOptions.imageOptimizerOptions = {
      region: Region.UsWest
    };
  }

  // `origin` is a named backend on the service.
  // Requests with `imageOptimizerOptions` are proxied through to Image Optimizer.
  // Other requests are sent to the `origin` backend directly.
  fetchOptions.backend = 'origin';
  return await fetch(event.request.url, fetchOptions);
}
```
</Panel>

<Panel id="go">

The Image Optimizer Go SDK documentation is available in our Go [SDK reference](https://pkg.go.dev/github.com/fastly/compute-sdk-go@v1.6.0/fsthttp/imageopto).

```go
package main

import (
	"context"
	_ "embed"
	"fmt"
	"github.com/fastly/compute-sdk-go/fsthttp"
	"github.com/fastly/compute-sdk-go/fsthttp/imageopto"
	"io"
	"regexp"
)

var imgRegex = regexp.MustCompile(`(?i)\.(?:gif|png|jpe?g|webp|avif|jxl|heic)$`)

func main() {
	fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {
		if imgRegex.MatchString(r.URL.Path) {
			// Proxy request to image optimizer if we are dealing with an image.
			r.ImageOptimizerOptions = &imageopto.Options{
				Region: imageopto.RegionUsWest,
			}
		}

		// `origin` is a named backend on the service.
		// Requests with `ImageOptimizerOptions` are proxied through to Image Optimizer.
		// Other requests are sent to the `origin` backend directly.
		resp, err := r.Send(ctx, "origin")
		if err != nil {
			w.WriteHeader(fsthttp.StatusBadGateway)
			fmt.Fprintln(w, err)
			return
		}

		w.Header().Reset(resp.Header.Clone())
		io.Copy(w, io.NopCloser(resp.Body))
	})
}
```

</Panel>
 -->

</Panel>
</TabbedPanels>

## 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 dimensions or visual fidelity. You can [modify these in the web interface](/guides/full-site-delivery/image-optimization/about-fastly-image-optimizer/#configuring-default-image-settings). Many of these can be further overridden or customized by providing explicit [configuration directives](#configuration) as query parameters or headers:

- `jpg`, `pjpg`, and `webp` images will optimized automatically with default quality of 85.
- All metadata (for example, EXIF, XMP, C2PA manifests, 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. These behaviors do not apply to `png` or `webp` images.
- If the source image contains orientation metadata, this orientation will be applied directly to the image data and metadata will be removed.
- The original `Vary` response header from origins will be removed by IO. See [limitations](#limitations-and-constraints).

## 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:

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

### Query parameters

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

| Parameter        | Description |
| :---             | :--- |
| [`auto`](/reference/io/auto)           | Enable optimization features automatically. |
| [`bg-color`](/reference/io/bg-color)       | Set the background color of an image. |
| [`blur`](/reference/io/blur)           | Set the blurriness of the output image. |
| [`brightness`](/reference/io/brightness)     | Set the brightness of the output image. |
| [`bw`](/reference/io/bw)     | Convert an image to black and white. |
| [`canvas`](/reference/io/canvas)         | Increase the size of the canvas around an image. |
| [`contrast`](/reference/io/contrast)       | Set the contrast of the output image. |
| [`crop`](/reference/io/crop)           | Remove pixels from an image. |
| [`disable`](/reference/io/disable)        | Disable functionality that is enabled by default. |
| [`dpr`](/reference/io/dpr)            | Serve correctly sized images for devices that expose a device pixel ratio.|
| [`enable`](/reference/io/enable)         | Enable functionality that is disabled by default. |
| [`fit`](/reference/io/fit)            | Set how the image will fit within the size bounds provided. |
| [`format`](/reference/io/format)         | Specify the output format to convert the image to. |
| [`frame`](/reference/io/frame)          | Extract the first frame from an animated image sequence. |
| [`height`](/reference/io/height)         | Resize the height of the image. |
| [`level`](/reference/io/level)          | Specify the level constraints when converting to video. |
| [`metadata`](/reference/io/metadata)          | Control which metadata fields are preserved during transformation. |
| [`optimize`](/reference/io/optimize)       | Automatically apply optimal quality compression. |
| [`orient`](/reference/io/orient)         | Change the cardinal orientation of the image. |
| [`pad`](/reference/io/pad)            | Add pixels to the edge of an image. |
| [`precrop`](/reference/io/precrop)        | Remove pixels from an image before any other transformations occur. |
| [`profile`](/reference/io/profile)        | Specify the profile class of application when converting to video. |
| [`quality`](/reference/io/quality)        | Optimize the image to the given compression level for lossy file formatted images. |
| [`resize-filter`](/reference/io/resize-filter)  | Specify the resize filter used when resizing images. |
| [`saturation`](/reference/io/saturation)     | Set the saturation of the output image. |
| [`sharpen`](/reference/io/sharpen)        | Set the sharpness of the output image. |
| [`trim`](/reference/io/trim)           | Remove pixels from the edge of an image. |
| [`viewbox`](/reference/io/viewbox)           | Remove explicit `width` and `height` properties in SVG output. |
| [`width`](/reference/io/width)          | Resize the width of the image. |

### Header parameters

| Header        | Description |
| :---             | :--- |
| [`X-Fastly-Imageopto-Montage`](/reference/io/montage) | Combine up to four images into a single displayed image. |
| [`X-Fastly-Imageopto-Overlay`](/reference/io/overlay) | Overlay 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`
1. `trim`
1. `crop`
1. `orient`
1. `width` `height` `dpr` `fit` `resize-filter` `disable` `enable`
1. `pad` `canvas` `bg-color`
1. `brightness` `contrast` `saturation` `bw`
1. `sharpen`
1. `blur`
1. `X-Fastly-Imageopto-Overlay`
1. `format` `auto` `optimize` `quality` `profile` `level` `metadata`

If an `X-Fastly-Imageopto-Montage` header is specified, all other IO parameters 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 parameters). Each transformation is cached as a variant of the original image, and thus the total number of unique transformations is subject to the Vary objects [count limit](https://docs.fastly.com/products/network-services-resource-limits#vcl-and-configuration-limits).

> **IMPORTANT:** Image optimization will only be applied to cacheable responses, and for services created on or after May 2, 2023, a minimum cache TTL of 60 seconds is enforced on transformed images (the original image is also cached and has no minimum TTL).
>
> 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](/solutions/examples/enable-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. You can, however, allow passthrough of unknown query parameters.

<!-- TabbedPanels component: 
<Panel id="cdn-services">

Opt in to query parameters by changing the value of the `X-Fastly-Imageopto-Api` header:
```vcl
set req.http.X-Fastly-Imageopto-Api = "fastly; qp=*";
```

</Panel>
<Panel id="compute-services">

Opt in to query parameters using the SDKs by setting `preserve_query_string_on_origin_request` in `ImageOptimizerOptions`:

```rust compile_fail
let mut io_options = ImageOptimizerOptions::from_region(ImageOptimizerRegion::UsEast);
io_options.preserve_query_string_on_origin_request = Some(true),
```

</Panel>
 -->

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

<!-- TabbedPanels component: 
<Panel id="cdn-services">

The query string normalization described above happens prior to the `vcl_hash` subroutine and the IO query parameters 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:

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

</Panel>
<Panel id="compute-services">

In Compute, a source image and all of its transforms share the same [surrogate key](/guides/full-site-delivery/purging/working-with-surrogate-keys/). As a result, purging an image in Compute requires using the [Purge API](/reference/api/purging/#purge-tag).

For example, say that you have this image and its associated transforms:

```text
https://example.com/image.jpg
https://example.com/image.jpg?width=200
https://example.com/image.jpg?width=350&crop=1:1
```

The surrogate key is calculated by taking the hex-encoded SHA-256 digest of the following origin request URL (without IO parameters):

`https://example.com/image.jpg`

You can generate this value with:

```bash
echo -n "https://example.com/image.jpg" | sha256
```

which returns `e5db82b5bf63d49d80c5533616892d3386f43955369520986d67653c700fc53c`.

Then issue an API purge to that surrogate key. For example:

```bash
curl -X POST "https://api.fastly.com/service/YOUR_SERVICE_ID/purge/e5db82b5bf63d49d80c5533616892d3386f43955369520986d67653c700fc53c" -H "Fastly-Key: YOUR_FASTLY_TOKEN"
```

After the purge succeeds, the source image and all of its transformed variations are removed from cache.

Keep in mind that the `Request::set_surrogate_key` method is not supported. Instead, set a `Surrogate-Key` explicitly as a response header from your origin and purge using that.

> **IMPORTANT:** Purge all is not supported for images delivered from IO using compute.

</Panel>
 -->

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:

```http
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.

<Fiddle id='475a0d98' />

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
- Not specifying an output format for an `HEIC` source image
- Unsupported Content-Encoding
- Gzipped body exceeds maximum length
- Gzipped body could not be decoded
- Invalid status
- Response is pass
- Response is not cacheable
- SVG output exceeds 50MB

## Authenticating IO requests

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. One solution is to implement transformation 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`.

<!-- TabbedPanels component: 
<Panel id="cdn-services">

<Fiddle id='0321670a' />

</Panel>
<Panel id="compute-services">

```rust
use fastly::image_optimizer::{
    ImageOptimizerOptions, ImageOptimizerRegion,
};
use fastly::{Error, Request, Response};
use regex::Regex;
use serde::{Deserialize, Serialize};

use std::collections::HashMap;

#[derive(Debug, Serialize, Deserialize)]
struct ClassMapping {
    crop: Option<&'static str>,
    width: Option<&'static str>,
}

#[fastly::main]
fn main(mut req: Request) -> Result<Response, Error> {
    let image_regex = Regex::new(r"(?i)(?:gif|png|jpe?g|webp|avif|jxl|heic)\z").unwrap();
    let url_path = req.get_path();
    let io_classes = HashMap::from([
        (
            "large",
            ClassMapping {
                crop: Some("16:9,smart"),
                width: Some("640"),
            },
        ),
        (
            "medium",
            ClassMapping {
                crop: Some("4:3,smart"),
                width: Some("320"),
            },
        ),
        (
            "small",
            ClassMapping {
                crop: Some("1:1,smart"),
                width: Some("100"),
            },
        ),
        (
            "default",
            ClassMapping {
                crop: None,
                width: Some("640"),
            },
        ),
    ]);

    // Only images go to Image Optimizer using the regex above or assuming an images directory
    if url_path.contains("/images/") || image_regex.is_match(url_path) {
        let io_options = ImageOptimizerOptions::from_region(ImageOptimizerRegion::UsWest);
        let mut params: HashMap<String, String> = req.get_query()?;
        // only allow the class params to be passed into your application
        // disallow using raw IO parameters
        params = params.into_iter().filter(|(k, _v)| k == "class").collect();

        // match the mapping to the sizes you want to use
        // we purposefully set `"default"` so the last unwrap is safe
        let class_param: &ClassMapping = io_classes
            .get(
                params
                    .get("class")
                    .unwrap_or(&String::from("default"))
                    .as_str(),
            )
            .unwrap();
        req.set_query(&class_param)?;

        req = req.with_image_optimizer(io_options);
        return Ok(req.send("origin")?);
    }

    // all other requests go to the normal path
    Ok(req.send("origin")?)
}
```

</Panel>
 -->

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

## Lossy vs. lossless output

IO supports both lossy and lossless images for input and output. Lossless output is available for `JPEGXL` and `WebP` as well as `PNG` and `GIF`, which are lossless formats to begin with. If your source image is a lossless format, the output automatically defaults to lossless if the specified output format allows it. This means when using a `PNG` source with `format=webp`, `format=jxl`, or `format=auto`, the output image is lossless by default.

IO does not support lossless output for `AVIF`.

### Forcing lossy output

Lossless output preserves all image data which also means it produces larger file sizes. This may be undesirable when delivering images over the web. To ensure lossy output in cases when your source format is lossless:

* Use `format=auto` with a `quality` value less than `100` which also intelligently chooses the output format.
* Use `format=webply` for lossy `WebP`.
* Use `format=jxl` with a `quality` value less than `100` for lossy `JPEGXL`.

### Forcing lossless output

To force lossless output even in cases where your source image is lossy:

* Use `format=auto` with `quality=100`.
* Use `format=webpll` for lossless `WebP`.
* Use `format=jxl` with `quality=100` for lossless `JPEGXL`.

## 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](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images) web technologies.

### Pixel density

Using the [`srcset`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset) attribute, it's possible to define images to be used at different **display pixel densities**, which works well with the [`width`](/reference/io/width) and [`dpr`](/reference/io/dpr) parameters.

```html
<img srcset="/io-demo/image.jpg?width=320&dpr=1.5 1.5x,
             /io-demo/image.jpg?width=320&dpr=2 2x"
     src="/io-demo/image.jpg?width=320"/>
```

### Art direction

Use the HTML5 [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture) element to deliver different image crops at different browser viewport sizes, a technique called **art direction**:

```html
<picture>
  <source srcset="/io-demo/image.jpg?width=600&crop=16:9" media="(min-width: 600px)"/>
  <img src="/io-demo/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:

```html
<picture>
  <source type="image/webp" srcset="/io-demo/image.webp"/>
  <source type="image/png" srcset="/io-demo/image.png"/>
  <img src="/io-demo/image.jpg"/>
</picture>
```

Learn more about [which image formats are supported in which browsers](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types).

### 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`](https://html.spec.whatwg.org/multipage/media.html#attr-video-playsinline) attribute, the [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/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:

```html
<video width="300" height="224" playsinline autoplay muted loop>
    <source src="/io-demo/image.gif?format=mp4" type="video/mp4" />
</video>
```

## Origin failover

Sometimes you may want to have more than one origin, often for redundancy purposes (e.g., primary: Amazon S3, secondary: Google Cloud Storage). If a resource does not exist in the primary origin, or the primary is unavailable, then we can perform a `restart` and try the secondary origin. We have a [code example](/solutions/examples/failover-to-a-secondary-backend) showing how to do this for normal resources, but there are some caveats to implementing this solution with IO:

- With IO enabled, query parameters will be stripped from the request URL after `vcl_hash`, so won't be present on the restarted request. This can be solved by storing the original request URL in a temporary request header in `vcl_recv` and reinstating it upon restart.
- To ensure that IO draws from the same pre-transform image cache, it's important that shielding is enabled on the primary backend, and that the restart happens on the shield.

Here is an example of how to do this:

<Fiddle id="cd724b3d" />

## Limitations and constraints

Keep the following things in mind when using Image Optimizer.

### File size and dimension limits

Image Optimizer enforces the following file size and dimension limits:

* 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 output image area for AVIF images is 4,096 x 4,096 pixels. AVIF is a premium feature of Fastly's Image Optimizer and choosing it as an encoding format will increase your bill. Specific charges will appear on your service order.
* The maximum output image dimensions for SVG images are 1,600 x 1,600 pixels.
* The maximum number of frames an animated GIF can contain is 1,000.

### Supported image formats

Image Optimizer supports the following image formats:

* We support input images in AVIF, GIF, HEIC, JPEG, JPEGXL, PNG, or WEBP format. HEIC sequence files are supported, but map to a single frame for the output and do not preserve animation.
* We can produce output images in AVIF, GIF, JPEG, JPEGXL, MP4, PNG, SVG, or WEBP format.

### VCL service requirements

When using Image Optimizer on VCL services, the following requirements apply:

* Image Optimizer will only process requests that are eligible for caching. If the request passes through `vcl_pass` before reaching origin, the response image will not be transformed.
* Image Optimizer is incompatible with the [Segmented Caching](/guides/full-site-delivery/caching/segmented-caching) feature. If Image Optimizer is enabled, Segmented Caching is disabled automatically.
* The `Vary` response header is removed by the Image Optimizer processor automatically after `vcl_fetch` execution at [shield POPs](/reference/glossary#term-shield-pop), so the original `Vary` response header from origins is not passed to downstream clients including edge POPs. This is to avoid multiple variations of the same original of transformed image being cached individually. We recommend also removing the `Vary` header in your service's `vcl_fetch` to ensure this behavior is also applied for requests received directly by shield POPs (the relevant VCL is included in our [standard VCL boilerplate](/guides/full-site-delivery/fastly-vcl/about-fastly-vcl)).
If you need to satisfy [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#cors_and_caching) by returning an Origin response header that matches the inbound Origin request header, we recommend adding that header in `vcl_deliver` at the edge POPs. Doing so allows a single cached copy of the response to be reused, while still letting you “customize” the header for different client origins. This approach applies to any request, but for Image Optimizer it is essential, because responses that pass through Image Optimizer cannot have cached variants. For example:

```vcl context="sub vcl_deliver { ... }"
if (fastly.ff.visits_this_service == 0 && resp.http.Access-Control-Allow-Origin) {
  set resp.http.Vary:Origin = "";
}
```

## Compute platform limitations

When using Image Optimizer on Compute, the following limitations apply:

* Image Optimizer is available on the Compute platform through our SDKs as part of Fastly's [Beta program](https://docs.fastly.com/products/fastly-product-lifecycle#beta). Any request sent to Image Optimizer, including through the SDK, counts as a [billable image request](https://docs.fastly.com/products/image-optimizer#billing) for the Image Optimizer product.
* The [Overlay](/reference/io/overlay) and [Montage](/reference/io/montage) features are not supported.
* Purge works differently on Compute. See the [purging images example](/reference/io/#purging-images-from-the-fastly-cache).
* When setting a hostname for the origin request, the hostname or override host defined on the backend is used. If you explicitly set the `Host` header, it is not passed through.
* Not all Request methods are respected. For example, `set_ttl`, `set_surrogate_key`, and `set_stale_while_revalidate` are ignored. Cache time defaults to the TTL returned by the origin.
* Response headers may differ from those returned by VCL services. Origin response headers are preserved, as are headers added by Image Optimizer (such as `Fastly-Io-Info`). However, infrastructure headers like `X-Cache`, `X-Cache-Hits`, and `X-Served-By` may only reflect the edge server that delivered the response to the end user, rather than showing multiple values from other POPs in the cache path (for example, the shield).
* In the Rust SDK, `Request::send_async` and `Request::send_async_streaming` are not supported with Image Optimizer.

