# Image Processor quickstart

This guide instructs you through requesting your first derived image from an application. By the end you will have:

- Image Processor turned on for one application.
- A cache setting that stores each transformation as its own object.
- A Rules Engine rule that sends image requests to the module.
- A resized image returned from a URL you wrote.

Four objects carry that result, and each one is linked to the one before it. The **application** holds the module switch. The **cache setting** belongs to the application and decides that two different transformations are two different cached objects. The **rule** belongs to the application, matches image requests, and applies both the cache setting and the **Optimize Images** behavior. The image URL then carries the transformation in its `ims` query string. A request that no rule matches is delivered unprocessed, so the rule is what makes the query string mean anything.

---

Select the interface you will use. The prerequisites and every stage below follow that choice.

## Prerequisites

- An [Azion account](/en/documentation/fundamentals/creating-account/).
- An application that already delivers images from an origin. To create one, refer to [Applications quickstart](/en/documentation/platform/applications/quickstart/).
- The path of one image the application serves, so you can request it at the end.

**Console**

- Access to Azion Console. To sign in, refer to [Access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**CLI**

- The [Azion CLI](/en/documentation/devtools/cli/) installed and authorized.

**API**

- A [personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/) and `curl`.

---

## Turn on Image Processor

The module is a switch on the application, and it is off until you set it. This stage turns on two modules.

**Application Accelerator** is the second for one reason: the field that varies the cache by a query string belongs to it, and the cache setting uses that field. Processing an image does not require the module, but caching each transformation separately does.

**Console**

To turn on both modules in Azion Console:

1. **Open the application**

   Access [Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/) > **Applications**, then select the application that delivers your images.

2. **Go to the Main Settings tab**

3. **Turn on Image Processor**

   In the **Modules** section, turn on **Image Processor**, described as *Enable dynamic image editing options*.

4. **Turn on Application Accelerator**

   The toggle is in the same section.

5. **Select Save**

The application now carries both modules, and the **Optimize Images** behavior becomes available to its rules.

**CLI**

One command sets both modules. Replace `<application_id>` with [your application ID](/en/documentation/guides/application-development/getting-started/configure-main-settings/):

1. **Run the update command**

   ```bash
   azion update application --application-id <application_id> --image-processor true --application-accelerator true
   ```

2. **Read the output**

   The command confirms the application it changed:

   ```text
   Updated Application with ID <application_id>
   ```

The application now carries both modules, and the **Optimize Images** behavior becomes available to its rules.

**API**

One request sets both modules. Replace `[TOKEN VALUE]` with your personal token and `<application_id>` with [your application ID](/en/documentation/guides/application-development/getting-started/configure-main-settings/):

1. **Send the update request**

   ```bash
   curl --request PATCH \
     --url https://api.azion.com/v4/workspace/applications/<application_id> \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "modules": {
       "application_accelerator": { "enabled": true },
       "image_processor": { "enabled": true }
     }
   }'
   ```

2. **Read the response**

   A `202` carries `"state": "pending"`, because the change is still propagating. The `modules` object of the response echoes every module of the application, including the ones you left alone:

   ```json
   {
     "cache": { "enabled": true },
     "functions": { "enabled": false },
     "application_accelerator": { "enabled": true },
     "image_processor": { "enabled": true }
   }
   ```

The application now carries both modules, and the **Optimize Images** behavior becomes available to its rules.

---

## Create a cache setting that varies on the ims query string

Without this step the cache cannot tell one transformation from another, and it may answer a request for a 400 pixel image with a 200 pixel one.

**Console**

To create the cache setting in Azion Console:

1. **Go to the Cache Settings tab**

2. **Select + Cache**

3. **Name the cache setting**

   In **Name**, enter `images`.

4. **Expand Cache vary by Query String**

   The panel is in the **Application Accelerator** section.

5. **Set Behavior to Allowlist**

6. **Add the ims field**

   In **Fields**, enter `ims`.

7. **Select Save**

The application now has a cache setting that stores one object per distinct `ims` value.

**CLI**

The create flags do not reach the maximum age, so the command sends the whole body from a file.

1. **Write the cache setting to a file**

   Save the following as `cache-setting.json`:

   ```json
   {
     "name": "images",
     "browser_cache": { "behavior": "honor" },
     "modules": {
       "cache": { "behavior": "override", "max_age": 31536000 },
       "application_accelerator": {
         "cache_vary_by_querystring": {
           "behavior": "allowlist",
           "fields": ["ims"],
           "sort_enabled": true
         }
       }
     }
   }
   ```

   `31536000` seconds is the ceiling of `max_age`, which suits images because they change rarely.

2. **Create the cache setting**

   Replace `<application_id>` with [your application ID](/en/documentation/guides/application-development/getting-started/configure-main-settings/):

   ```bash
   azion create cache-setting --application-id <application_id> --file cache-setting.json
   ```

   The command prints the id of the new cache setting:

   ```text
   Created Cache Settings configuration with ID 123464
   ```

3. **Read the cache setting back**

   ```bash
   azion describe cache-setting --application-id <application_id> --cache-setting-id 123464 --format json
   ```

   The output reports the `ims` allowlist and the maximum age the file set.

The application now has a cache setting that stores one object per distinct `ims` value. Record the id the command printed, because the rule applies it. For every flag the command accepts, refer to [Azion CLI create](/en/documentation/devtools/cli/resources/).

**API**

One request carries the cache behavior and the query string allowlist together.

1. **Send the create request**

   Replace `<application_id>` with [your application ID](/en/documentation/guides/application-development/getting-started/configure-main-settings/):

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/applications/<application_id>/cache_settings \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "name": "images",
     "browser_cache": { "behavior": "honor" },
     "modules": {
       "cache": { "behavior": "override", "max_age": 31536000 },
       "application_accelerator": {
         "cache_vary_by_querystring": {
           "behavior": "allowlist",
           "fields": ["ims"],
           "sort_enabled": true
         }
       }
     }
   }'
   ```

   `31536000` seconds is the ceiling of `max_age`, which suits images because they change rarely.

2. **Read the response**

   A `201` carries `"state": "executed"` and the cache setting it created. The response brings `modules.cache.max_age` back as `31536000` and echoes `cache_vary_by_querystring` exactly as you sent it.

   Record `data.id`, such as `123463`, because the rule applies it.

The application now has a cache setting that stores one object per distinct `ims` value.

For the rest of the fields a cache setting carries, including how long an object stays cached, refer to [Cache Settings](/en/documentation/platform/applications/cache/cache-settings/).

---

## Create a rule that sends image requests to the module

The rule is what turns the query string into a transformation. It matches requests for image paths, applies the cache setting you created, and adds the **Optimize Images** behavior.

**Console**

To create the rule in Azion Console:

1. **Go to the Rules Engine tab**

2. **Select + Rule**

3. **Name the rule**

   In **Name**, enter `Optimize images`.

4. **Select Request Phase**

5. **Select the variable**

   In the criteria, select `${request_uri}`.

6. **Select the operator matches**

7. **Enter the argument**

   Enter `\.(jpg|jpeg|gif|bmp|png|ico|webp|avif)`.

8. **Add the Set Cache Policy behavior**

   In the behaviors, select **Set Cache Policy**, then choose the `images` cache setting.

9. **Select Add Behavior**

10. **Select Optimize Images**

11. **Select Save**

Every request for a path ending in one of those extensions now reaches Image Processor, carries the `images` cache setting, and is processed when its URL asks for a transformation.

**CLI**

The criteria carry `${request_uri}`, which a shell expands, and the argument carries backslashes, so the rule goes in a file.

1. **Write the rule to a file**

   Save the following as `rule.json`, with the id of your cache setting in the `set_cache_policy` behavior:

   ```json
   {
     "name": "Optimize images",
     "description": "Apply the cache setting and optimize images",
     "active": true,
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${request_uri}",
           "operator": "matches",
           "argument": "\\.(jpg|jpeg|gif|bmp|png|ico|webp|avif)"
         }
       ]
     ],
     "behaviors": [
       { "type": "set_cache_policy", "attributes": { "value": 123464 } },
       { "type": "optimize_images" }
     ]
   }
   ```

   One rule carries both behaviors, and `optimize_images` takes no attributes.

2. **Create the rule**

   ```bash
   azion create rules-engine --application-id <application_id> --phase request --file rule.json
   ```

   The command prints the id of the new rule:

   ```text
   Created Rules Engine with ID 234571
   ```

Every request for a path ending in one of those extensions now reaches Image Processor, carries the `images` cache setting, and is processed when its URL asks for a transformation.

**API**

The criteria carry `${request_uri}`, which a shell expands, and the argument carries backslashes, so the body is sent from a file.

1. **Write the rule to a file**

   Save the following as `rule.json`, with the id of your cache setting in the `set_cache_policy` behavior:

   ```json
   {
     "name": "Optimize images",
     "description": "Apply the cache setting and optimize images",
     "active": true,
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${request_uri}",
           "operator": "matches",
           "argument": "\\.(jpg|jpeg|gif|bmp|png|ico|webp|avif)"
         }
       ]
     ],
     "behaviors": [
       { "type": "set_cache_policy", "attributes": { "value": 123463 } },
       { "type": "optimize_images" }
     ]
   }
   ```

   One rule carries both behaviors, and `optimize_images` takes no attributes.

2. **Send the create request**

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/applications/<application_id>/request_rules \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data @rule.json
   ```

3. **Read the response**

   A `202` carries `"state": "pending"`, because the rule is still propagating. It echoes the criteria and both behaviors, and it carries the `order` the rule holds among the rules of the application.

Every request for a path ending in one of those extensions now reaches Image Processor, carries the `images` cache setting, and is processed when its URL asks for a transformation.

> **Optional**
>
> Converting an image to WEBP or AVIF requires the request to carry `Accept: image/webp` or `Accept: image/avif`. The **Add Request Header** behavior adds it to the same rule, so the conversion stops depending on what the browser sent. In the Azion CLI and the API, it is a behavior of type `add_request_header`, whose `attributes` carry `"value": "Accept: image/webp"`. For the behavior's fields, refer to [Image Processor settings](/en/documentation/platform/applications/image-processor/settings/).

---

## Request a derived image

Ask for a width and see the response change.

Request one of your images with an `ims` query string, replacing the host and the path with your own:

```bash
curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download} bytes\n" \
  -H "Accept: image/webp,image/*" \
  "https://www.example.com/images/photo.jpg?ims=400x"
```

The response reports its status, its type, and its size:

```text
200 image/webp 8312 bytes
```

Request the same image with no query string and compare the size. The processed response is smaller, and it may also carry a different format from the file on your origin, because Image Processor delivers WEBP to the browsers that accept it.

To confirm the module handled the response rather than the origin, read the headers:

```bash
curl -sI -H "Accept: image/webp" "https://www.example.com/images/photo.jpg?ims=400x"
```

A processed response carries `x-ims: Enabled` and the size of the source image before the transformation:

```text
HTTP/2 200
content-type: image/webp
x-ims: Enabled
x-original-image-size: 484156
```

You now have an application that transforms images on request, and a URL that describes the transformation.

> **Tip**
>
> Keep `ims=` as the last parameter in the URL. A request that carries another query string parameter after it may return a `504` error.

---

## Next steps

- [Image Processor URL parameters](/en/documentation/platform/applications/image-processor/url-parameters.md): Every operation the ims query string expresses, beyond the resize you just used.
- [Image delivery](/en/documentation/platform/applications/image-processor/image-delivery.md): What happens between the request and the derived image, and why the rule is required.
- [Applications best practices](/en/documentation/platform/applications/best-practices.md#image-processor): The quality value, the caching choices, and the headers that keep a transformation cheap.
- [Applications limits](/en/documentation/platform/applications/limits.md#image-processor): The bounds on one image, and what counts against the monthly Images meter.
- [Configure Image Processor on an application](/en/documentation/guides/application-performance/delivery-optimization/process-images.md): The same setup with the full API v3 object, when your automation still uses it.
- [Troubleshoot Applications](/en/documentation/platform/applications/troubleshooting.md#image-processor): What to check when an image comes back unprocessed or in the wrong format.
