# Filter files

Robot: `/file/filter`

🤖/file/filter directs files to different encoding Steps based on your conditions.

Think of this <dfn>Robot</dfn> as an `if/else` condition for building advanced file conversion workflows. With it, you can filter and direct certain uploaded files depending on their metadata.

The <dfn>Robot</dfn> has two modes of operation:

* Constructing conditions out of arrays with 3 members each. For example, `["${file.size}", "<=", "720"]`
* Writing conditions in JavaScript. For example, `${file.size <= 720}`. See also [Dynamic Evaluation](/docs/topics/dynamic-evaluation.md).

If you want a `/file/filter` Step to pass every input file through unchanged, leave `accepts` and
`declines` unset, or set them to `null`. Do not use `"accepts": "true"` for this: plain strings
are treated as JavaScript expressions only when they use the `${...}` form, such as `"${true}"`.

Passing JavaScript allows you to implement logic as complex as you wish, however it’s slower than combining arrays of conditions, and will be charged for per invocation via [🤖/script/run](/docs/robots/script-run.md).

### Conditions as arrays

The `accepts` and `declines` parameters can each be set to an array of arrays with three members:

1. A value or job variable, such as `${file.mime}`
2. One of the following operators: `=`, `==`, `===`, `<`, `>`, `<=`, `>=`, `!=`, `!==`, `regex`, `!regex`, `includes`, `!includes`, `empty`, `!empty`
3. A value or job variable, such as `50` or `"foo"`

Examples:

* `[["${file.meta.width}", ">", "${file.meta.height}"]]`
* `[["${file.size}", "<=", "720"]]`
* `[["${file.size}", ">", "20mb"]]`
* `[["720", ">=", "${file.size}"]]`
* `[["${file.mime}", "regex", "image"]]`

When you match against `${file.mime}`, the value is typically based on Transloadit’s
server-side metadata extraction in the normal upload flow, rather than only the MIME type reported
by the client or browser. This makes `/file/filter` suitable for rejecting mislabeled files.
Depending on the file container and the detection tools involved, some formats may be reported under
closely related MIME types such as `image/heic` or `image/heif`.

If you only want formats that browsers consistently render, prefer an explicit allowlist such as
`^(image/jpeg|image/png|image/gif|image/webp|image/avif)$` over a broad `^image/` rule.

For numeric comparisons (`<`, `>`, `<=`, `>=`), you can use human-readable byte values such as `"20mb"`, `"1gb"`, or `"512kb"`. These use binary (1024-based) multipliers. Supported units: `b`, `kb`, `mb`, `gb`, `tb`, `pb` (and their IEC equivalents `kib`, `mib`, `gib`, `tib`, `pib`).

The `includes` and `!includes` operators work with arrays or strings (strings use substring checks).

> [!Warning]
> If you would like to match against a `null` value or a value that is not present (like an audio file does not have a `video_codec` property in its metadata), match against `""` (an empty string) instead. We’ll support proper matching against `null` in the future, but we cannot easily do so right now without breaking backwards compatibility.

### Conditions as JavaScript

The `accepts` and `declines` parameters can each be set to strings of JavaScript, which return a boolean value.

Examples:

* `${file.meta.width > file.meta.height}`
* `${file.size <= 720}`
* `${/image/.test(file.mime)}`
* `${Math.max(file.meta.width, file.meta.height) > 100}`

As indicated, we charge for this via [🤖/script/run](/docs/robots/script-run.md). See also [Dynamic Evaluation](/docs/topics/dynamic-evaluation.md) for more details on allowed syntax and behavior.

Stage: ga

## Usage example

Reject files that are larger than 20 MB:

```json
{
  "steps": {
    "filtered": {
      "robot": "/file/filter",
      "use": ":original",
      "declines": [
        [
          "${file.size}",
          ">",
          "20mb"
        ]
      ],
      "error_on_decline": true,
      "error_msg": "File size must not exceed 20 MB"
    }
  }
}
```

## Parameters

* `interpolate`: Controls whether Assembly Variables are interpolated for individual instruction fields.

  By default, most Robot instruction fields interpolate Assembly Variables. Set this to `false` to treat every instruction field as literal text, or set an individual field path to `false` to treat only that field as literal text. For Robot-specific fields that are literal by default, set this to `true` or set that field path to `true` to opt back into interpolation.

  Use field names such as `path`, or dotted paths such as `ffmpeg.vf` for nested objects.

* `output_meta`: Allows you to specify a set of metadata that is more expensive on CPU power to calculate, and thus is disabled by default to keep your Assemblies processing fast.

  For images, you can add `"has_transparency": true` in this object to extract if the image contains transparent parts and `"dominant_colors": true` to extract an array of hexadecimal color codes from the image.

  For images, you can also add `"blurhash": true` to extract a [BlurHash](https://blurha.sh) string — a compact representation of a placeholder for the image, useful for showing a blurred preview while the full image loads.

  For videos, you can add the `"colorspace": true` parameter to extract the colorspace of the output video.

  For videos, you can also add `"interlaced": true` to detect whether the video is interlaced. This combines the cheap ffprobe `field_order` flag with a bounded `idet` sampling pass over the first frames of the source, exposing `interlaced`, `field_order`, and a diagnostic `interlace_detection` object under `file.meta`. This is computationally expensive and billed accordingly.

  For audio, you can add `"mean_volume": true` to get a single value representing the mean average volume of the audio file.

  You can also set this to `false` to skip metadata extraction and speed up transcoding.

* `user_meta`: Adds custom metadata to each file emitted by this Robot without modifying the file’s contents.

  The values are merged with any existing `user_meta` carried by the input file. If both objects contain the same key, this Robot’s value takes precedence. Assembly Variables are supported, for example `{ "internal_file_id": "${file.id}" }`.

* `result`: Whether the results of this Step should be present in the Assembly Status JSON

* `queue`: Setting the queue to 'batch', manually downgrades the priority of jobs for this step to avoid consuming Priority job slots for jobs that don't need zero queue waiting times

* `force_accept`: Force a Robot to accept a file type it would have ignored.

  By default, Robots ignore files they are not familiar with.
  [🤖/video/encode](/docs/robots/video-encode.md), for
  example, will happily ignore input images.

  With the `force_accept` parameter set to `true`, you can force Robots to accept all files thrown at them.
  This will typically lead to errors and should only be used for debugging or combatting edge cases.

* `ignore_errors`: Ignore errors during specific phases of processing.

  Setting this to `["meta"]` will cause the Robot to ignore errors during metadata extraction.

  Setting this to `["execute"]` will cause the Robot to ignore errors during the main execution phase.

  Setting this to `true` is equivalent to `["meta", "execute"]` and will ignore errors in both phases.

* `use`: Specifies which Step(s) to use as input.

  * You can pick any names for Steps except `":original"` (reserved for user uploads handled by Transloadit)
  * You can provide several Steps as input with arrays:
    ```json
    {
      "use": [
        ":original",
        "encoded",
        "resized"
      ]
    }
    ```
  * You can also tag input Steps with `as` to pass semantic intent to robots:
    ```json
    {
      "use": [
        {
          "name": ":original",
          "as": "image"
        },
        {
          "name": ":original",
          "as": "mask"
        }
      ]
    }
    ```

  > [!Tip]
  > That's likely all you need to know about `use`, but you can view [Advanced use cases](/docs/topics/use-parameter.md).

* `accepts`: Files that match at least one requirement will be accepted, or declined otherwise. If the value is `null`, all files will be accepted. If the array is empty, no files will be accepted. Omit this parameter or set it to `null` when you want the Step to pass every file through. Examples:

  `[["${file.mime}", "==", "image/gif"]]`
  `[["${file.size}", "<", "5kb"]]`

  For numeric comparisons (`<`, `>`, `<=`, `>=`), human-readable byte values such as `"20mb"`, `"1gb"`, or `"512kb"` are supported.

  If the `condition_type` parameter is set to `"and"`, then all requirements must match for the file to be accepted.

  If `accepts` and `declines` are both provided, the requirements in `accepts` will be evaluated first, before the conditions in `declines`.

* `declines`: Files that match at least one requirement will be declined, or accepted otherwise. If the value is `null` or an empty array, no files will be declined. Examples:

  `[["${file.size}", ">", "1024"]]`
  `[["${file.size}", ">", "20mb"]]`

  For numeric comparisons (`<`, `>`, `<=`, `>=`), human-readable byte values such as `"20mb"`, `"1gb"`, or `"512kb"` are supported.

  If the `condition_type` parameter is set to `"and"`, then all requirements must match for the file to be declined.

  If `accepts` and `declines` are both provided, the requirements in `accepts` will be evaluated first, before the conditions in `declines`.

* `condition_type`: Specifies the condition type according to which the members of the `accepts` or `declines` arrays should be evaluated. Can be `"or"` or `"and"`.

* `error_on_decline`: If this is set to `true` and one or more files are declined, the Assembly will be stopped and marked with an error.

* `error_msg`: The error message shown to your users (such as by Uppy) when a file is declined and `error_on_decline` is set to `true`.
