> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Eager and incoming transformations


Cloudinary's transformations can be used while uploading an asset in one of two ways:

* [Eager transformations](#eager_transformations): Warm up your cache by generating transformed assets during an upload call or on existing assets so that those transformations will already be available for delivery before your users access them for the first time. When used on upload, these transformations are generated in addition to storing the original asset. This is especially useful for transformations that require a lot of processing or for long videos that can take a while to generate. 
* [Incoming transformations](#incoming_transformations): Transform the original asset before storing it in Cloudinary. This can be useful for example to limit images to a maximum resolution or videos to a maximum duration. 

> **NOTE**: When configuring [upload presets](upload_presets#best_practices_for_upload_presets) with eager transformations, avoid using the same transformation in both incoming and eager transformations.

> **TIP**: You can see both of these features in action in the [video review sample project](video_review_sample_project).

## Eager transformations

Cloudinary can either transform your assets on demand, when first accessed by your visitors as 'lazy transformations', or when uploading or updating an asset, as **eager** transformations. Eager transformations are used to warm up your cache and are generated in addition to the originally uploaded asset. You can request multiple eager transformations during a single upload command or while updating an existing asset.

When transforming on demand during delivery, all transformed assets are generated on the fly, stored persistently, cached and delivered through a fast CDN. The time required for generating a transformation depends on various factors: original asset dimensions, asset file size, requested dimensions, applied effects and the processing required for specific transformations. Once generated for the first time on the first request of a visitor, the transformed asset is henceforth cached and delivered through a fast CDN for all subsequent requests. 

The eager approach requires a little planning, but is recommended if you want to make sure that all transformed assets are ready for fast delivery even for the first visitors to your assets. This is especially useful for [video transformations](video_manipulation_and_delivery), transformations that perform AI analyses, or other asynchronous operations, such as those performed by some Cloudinary [add-ons](cloudinary_add_ons). 

For these cases, you can eagerly generate the required transformations during the upload process so all transformed assets will already be available before your users access them for the first time. Alternatively, you can generate them for existing assets using the [explicit](image_upload_api_reference#explicit) methods. Eager transformations are also useful in the case that you want to enable **Strict Transformations** and limit access to dynamic URLs (for more information, see [Control access to assets](control_access_to_media)).

> **NOTE**:
>
> New derived assets are created if the URL differs in any way, even if the delivered result is the same. For example: 

> * If the order of the transformation parameters changes. For example, `w_300,c_scale` is considered a different transformation to `c_scale,w_300`, even though the delivered media looks the same.

> * If the file extension is different. For example, `.jpg` is considered a different transformation than `.jpeg`, or a JPEG file with no extension specified, even though a JPEG file is the delivered format in each case.

> * Whether or not the file format is specified as a transformation. For example, specifying `f_jpg` as a transformation parameter for a JPEG file is considered a different transformation than delivering the same transformation with a `.jpg` extension, even though a JPEG file is delivered in each case.

The `eager` parameter accepts either a single transformation or an array of transformations, where each transformation is represented by a hash of transformation parameters. 

For details on all available transformation parameters, see the [Transformation URL API Reference](transformation_reference).

> **NOTE**:
>
> When using the REST API rather than an SDK, the `eager` parameter receives a list of transformation strings separated with a pipe character (<code>&#124;). Chained transformations are separated with a slash (`/`). For example, the following eager value will generate 3 transformations: 

> * Crop out a 400x400 region centered on the largest detected face

> * Scale down to a width and height of 500 pixels

> * Crop out a 300x300 region with south gravity
> ```
eager=c_crop,w_400,h_400,g_face|w_500,h_500,c_scale|w_300,h_300,c_crop,g_south
```
> For more details, see [Uploading with a direct call to the REST API](client_side_uploading#direct_call_to_the_api).

### Eager transformations on upload

The following example uploads the `sample.jpg` image and then additionally generates two transformed images: 
   
1. Pad to a width of 400 pixels and height of 300 pixels.
2. Crop to a width of 260 pixels and a height of 200 pixels with north gravity. 

```multi
|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  eager: [
    {width: 400, height: 300, crop: "pad"}, 
    {width: 260, height: 200, crop: "crop", gravity: "north"}])
 
|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
  "eager" => [
    ["width" => 400, "height" => 300, "crop" => "pad"],
    ["width" => 260, "height" => 200, "crop" => "crop", "gravity" => "north"]]]);

|python
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"width": 400, "height": 300, "crop": "pad"},
    {"width": 260, "height": 200, "crop": "crop", "gravity": "north"}])

|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { eager: [
    { width: 400, height: 300, crop: "pad" }, 
    { width: 260, height: 200, crop: "crop", gravity: "north"} ]})
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().width(400).height(300).crop("pad"),
      new EagerTransformation().width(260).height(200).crop("crop").gravity("north"))));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().Width(400).Height(300).Crop("pad"),
   new EagerTransformation().Width(260).Height(200).Crop("crop").Gravity("north")}};
var uploadResult = cloudinary.Upload(uploadParams);

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
      Eager: "c_pad,h_300,w_400|c_crop,g_north,h_200,w_260"})

|android
MediaManager.get().upload("sample.jpg")
  .option("eager", Arrays.asList(
      new EagerTransformation().width(400).height(300).crop("pad"),
      new EagerTransformation().width(260).height(200).crop("crop").gravity("north"))).dispatch();

|swift
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setWidth(400).setHeight(300).setCrop("pad"),
    CLDTransformation().setWidth(260).setHeight(200).setCrop("crop").setGravity("north")])
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

|cli
cld uploader upload sample.jpg eager='w_400,h_300,c_pad|w_260,h_200,c_crop,g_north'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&eager=w_400,h_300,c_pad|w_260,h_200,c_crop,g_north&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

The delivery URLs for these eagerly generated transformations:
![sample.jpg padded to a width of 400 pixels and height of 300 pixels](https://res.cloudinary.com/demo/image/upload/w_400,h_300,c_pad/sample.jpg "with_code:false, with_image:false")

![sample.jpg cropped to a width of 260 pixels and a height of 200 pixels with north gravity](https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg "with_code:false, with_image:false")

> **TIP**: You can create an [upload preset](upload_presets) with the `eager` parameter and apply the preset to the upload.

### Apply named transformations

A named transformations is a pre-defined set of transformation parameters with a custom name for easy reference. Instead of applying each of the required transformations separately, you can apply a single named transformation to apply all the transformations defined for it.

The following example generates a resized image scaled to a width of 600 pixels with a Cloudinary logo as a watermark by applying via the named transformation:

```multi
|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  eager: [
    {transformation: "watermark"}])

|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
  "eager" => [
    ["transformation" => "watermark"]]]);

|python
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"transformation": "watermark"}])

|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { eager: [
    { transformation: "watermark" } ]})
.then(result => console.log(result)); 

|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().transformation("watermark"))));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().Transformation("watermark")}};
var uploadResult = cloudinary.Upload(uploadParams);

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
      Eager: "t_watermark"})

|android
MediaManager.get().upload("sample.jpg")
  .option("eager", Arrays.asList(
      new EagerTransformation().transformation("watermark"))).dispatch();

|swift
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setTransformation("watermark")])
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

|cli
cld uploader upload sample.jpg eager='t_watermark'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&eager=t_watermark&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

> **TIP**: Also consider using a [baseline transformation](transformation_reference#bl_baseline) (which requires a named transformation), as a way to reduce processing time and cost when applying multiple eager transformations to the same asset.

### Eager transformations on existing assets

You can generate eager transformations for previously uploaded assets using the [explicit](image_upload_api_reference#explicit) API method. 

The most common usage of this method is to eagerly generate transformations for assets that have already been uploaded, either so that they do not need to be generated on the fly when first accessed by users, or because [Strict transformations](control_access_to_media#strict_transformations) are enabled for your product environment and you cannot create transformed assets on the fly. You can also use this method to pre-generate transformations for [remotely fetched assets](fetch_remote_images).

The following example generates transformations for the already uploaded image with a Public ID of `docs/camera` as follows: 
   
1. Crop to a width and height of 400 pixels including the biggest face detected. 
2. Pad to a width of 660 pixels and a height of 400 pixels with a blue background. 

```multi
|ruby  
result = Cloudinary::Uploader
.explicit("docs/camera", 
  type: "upload",
  eager: [
    { width: 400, height: 400, 
	  crop: "crop", gravity: "face"}, 
	{ width: 660, height: 400, 
      crop: "pad", background: "blue"}])
 
|php_2
$result = $cloudinary->uploadApi()
->explicit("docs/camera", [
    "type" => "upload", 
    "eager" => [
	  [ "width" => 400, "height" => 400,
		"crop" => "crop", "gravity" => "face"],
	  [ "width" => 660, "height" => 400,
		"crop" => "pad", "background" => "blue"]]]);

|python
result = cloudinary.uploader\
.explicit("docs/camera", 
  type = "upload",
  eager = [
    { "width": 400, "height": 400,
	  "crop": "crop", "gravity": "face"},
	{ "width": 660, "height": 400,
	  "crop": "pad", "background": "blue"}])


|nodejs
cloudinary.v2.uploader
.explicit("docs/camera", 
  { type: "upload",
	eager: [
	  { width: 400, height: 400,
		crop: "crop", gravity: "face"}, 
	  { width: 660, height: 400,
		crop: "pad", background: "blue"} ]})
.then(result=>console.log(result)); 

  
|java
result = cloudinary.uploader()
.explicit("docs/camera", 
  ObjectUtils.asMap(
    "type", "upload",
    "eager", Arrays.asList(
      new EagerTransformation().width(400).height(400)
		.crop("crop").gravity("face"),
	  new Transformation().width(660).height(400)
		.crop("pad").background("blue"))));

|csharp
var explicitParams = new ExplicitParams("docs/camera"){
  Type = "upload",
  EagerTransforms = new List<Transformation>(){
    new EagerTransformation().Width(400).Height(400)
      .Crop("crop").Gravity("face"),
    new Transformation().Width(660).Height(400)
      .Crop("pad").Background("blue")}};
var explicitResult = cloudinary.Explicit(explicitParams);

|go
resp, err := cld.Upload.Explicit(ctx, uploader.ExplicitParams{
    PublicID: "docs/camera", 
    Type: "upload", 
    Eager: "w_400,h_400,c_crop,g_face|w_660,h_400,c_pad,b_blue"})

|dart
cloudinary.uploader().explicit(ExplicitParams("docs/camera",
    params: UploadParams(
        type: "upload",
        eager: [EagerTransformation(Transformation().resize(Resize.crop()..width(400)..height(400)..gravity(Gravity.south())))])));

|swift
let eager1 = CLDEagerTransformation()
  .setWidth(400).setHeight(400).setCrop("crop").setGravity("face")
let eager2 = CLDEagerTransformation()
  .setWidth(660).setHeight(400).setCrop("pad").setBackground("blue")
let params = CLDExplicitRequestParams().setEager([eager1, eager2])
let result = cloudinary.createManagementApi().explicit("docs/camera", params: params)

|curl
curl https://api.cloudinary.com/v1_1/demo/image/explicit -X POST --data 'type=upload&public_id==docs/camera&eager=w_400,h_400,c_crop,g_face|w_660,h_400,c_pad,b_blue&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af' 

|cli
cld uploader explicit "docs/camera" type="upload" eager='[{ "width": 400, "height": 400,"crop": "crop", "gravity": "face"},{ "width": 660, "height": 400,"crop": "pad", "background": "blue"}]'
```

The delivery URLs for these eagerly generated transformations:
![sample cropped to a width and height of 400 pixels with face gravity](https://res.cloudinary.com/demo/image/upload/w_400,h_400,c_crop,g_face/docs/camera.jpg "with_code:false, with_image:false")

![sample padded to a width of 660 pixels and a height of 400 pixels with north gravity](https://res.cloudinary.com/demo/image/upload/w_660,h_400,c_pad,b_blue/docs/camera.jpg "with_code:false, with_image:false")

> **NOTE**: When you request an eager transformation using `explicit`, the transformation is processed (and counted in your transformation quota) even if an identical derived asset already exists.

### Using automatic format in eager transformations

Specifying `f_auto` in an eager transformation doesn't eagerly generate derived assets for all formats. The [automatic format](transformation_reference#f_auto) parameter determines the optimal format based on the requesting browser at delivery time. Since there is no requesting browser during upload, `f_auto` has no effect in eager transformations. To ensure all format variants are available in advance, explicitly specify each format you need instead of using `f_auto`. 

As the extension is counted as part of the transformation, it is best practice not to include an extension in your delivery URLs, otherwise you would have to generate eager transformations not only for the `f` parameter, but also for the extension. 

This is an example of a URL using `f_auto` without an extension:

![Using f_auto](https://res.cloudinary.com/demo/image/upload/f_auto/sample "with_image:false")

```nodejs
cloudinary.image("sample", {fetch_format: "auto"})
```

```react
new CloudinaryImage("sample").delivery(format(auto()));
```

```vue
new CloudinaryImage("sample").delivery(format(auto()));
```

```angular
new CloudinaryImage("sample").delivery(format(auto()));
```

```js
new CloudinaryImage("sample").delivery(format(auto()));
```

```python
CloudinaryImage("sample").image(fetch_format="auto")
```

```php
(new ImageTag('sample'))
	->delivery(Delivery::format(
	Format::auto()));
```

```java
cloudinary.url().transformation(new Transformation().fetchFormat("auto")).imageTag("sample");
```

```ruby
cl_image_tag("sample", fetch_format: "auto")
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().FetchFormat("auto")).BuildImageTag("sample")
```

```dart
cloudinary.image('sample').transformation(Transformation()
	.delivery(Delivery.format(
	Format.auto())));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setFetchFormat("auto")).generate("sample")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().fetchFormat("auto")).generate("sample");
```

```flutter
cloudinary.image('sample').transformation(Transformation()
	.delivery(Delivery.format(
	Format.auto())));
```

```kotlin
cloudinary.image {
	publicId("sample")
	 delivery(Delivery.format(
	Format.auto())) 
}.generate()
```

```jquery
$.cloudinary.image("sample", {fetch_format: "auto"})
```

```react_native
new CloudinaryImage("sample").delivery(format(auto()));
```

Thus, instead of generating an eager transformation with `f_auto` in the URL, you need to generate an eager transformation for each of the [formats that are enabled](image_optimization#fauto_format_availability) for `f_auto` on your account. The following example specifies `f_avif`, and `f_webp,fl_awebp`, while setting the `format` parameter (that controls the URL file extension) to an empty string:

> **NOTE**: This also applies when configuring eager transformations in [upload presets](upload_presets#use_specific_formats_and_codecs_for_video_eager_transformations_instead_of_f_auto).

```multi

|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  eager: [
    {fetch_format: "avif", format: ""},
    {fetch_format: "webp", flags: "awebp", format: ""}])

|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
  "eager" => [
    ["fetch_format" => "avif", "format" => ""],
    ["fetch_format" => "webp", "flags" => "awebp", "format" => ""]]]);
  
|python
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"fetch_format": "avif", "format": ""},
    {"fetch_format": "webp", "flags": "awebp", "format": ""}])


|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { eager: [
    { fetch_format: "avif", format: "" },
    { fetch_format: "webp", flags: "awebp", format: "" } ]})
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("avif").format(""),
      new EagerTransformation().fetchFormat("webp").flags("awebp").format(""))));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().FetchFormat("avif").Format(""),
   new EagerTransformation().FetchFormat("webp").Flags("awebp").Format("")}};
var uploadResult = cloudinary.Upload(uploadParams);

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
      Eager: "f_avif|f_webp/fl_awebp"})

|android
MediaManager.get().upload("sample.jpg")
  .option("eager", Arrays.asList(
      new EagerTransformation().fetchFormat("avif").format(""),
      new EagerTransformation().fetchFormat("webp").flags("awebp").format(""))).dispatch();

|swift
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setFetchFormat("avif").setFormat(""),
    CLDTransformation().setFetchFormat("webp").setFlags("awebp").setFormat("")])
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

|cli
cld uploader upload sample.jpg eager='f_avif/|f_webp,fl_awebp/'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&eager=f_wdp|f_webp,fl_awebp&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

Response:

```
...
    "eager": [
    {
      "transformation": "f_avif/",
      "width": 864,
      "height": 576,
      "bytes": 37268,
      "format": "avif",
      "url": "http://res.cloudinary.com/demo/image/upload/f_avif/v1608208001/sample",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/f_avif/v1608208001/sample"
    },
    {
      "transformation": "f_webp,fl_awebp/",
      "width": 864,
      "height": 576,
      "bytes": 57116,
      "format": "webp",
      "url": "http://res.cloudinary.com/demo/image/upload/f_webp,fl_awebp/v1608208001/sample",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/f_webp,fl_awebp/v1608208001/sample"
    }
  ]
...
```

> **NOTE**: Even for still WebP images, the animated WebP flag is required, to match the parameter replacement performed on the CDN.

To use `f_auto` for videos, the eagerly generated transformations need to include `fetch_format` and `video_codec`, as follows:

```multi

|ruby  
Cloudinary::Uploader.upload("sample.mp4",
  eager: [
    {fetch_format: "webm", video_codec: "vp9", format: ""}, 
    {fetch_format: "mp4", video_codec: "av1", format: ""},
    {fetch_format: "mp4", video_codec: "h265", format: ""},
    {fetch_format: "mp4", video_codec: "h264", format: ""}])

|php_2
$cloudinary->uploadApi()->upload("sample.mp4", [ 
  "eager" => [
    ["fetch_format" => "webm", "video_codec" => "vp9", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "av1", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h265", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h264", "format" => ""]]]);

|python
cloudinary.uploader.upload("sample.mp4", 
  eager = [
    {"fetch_format": "webm", "video_codec": "vp9", "format": ""},
    {"fetch_format": "mp4", "video_codec": "av1", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h265", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h264", "format": ""}])

|nodejs
cloudinary.v2.uploader
.upload("sample.mp4", 
  { eager: [
    { fetch_format: "webm", video_codec: "vp9", format: "" }, 
    { fetch_format: "mp4", video_codec: "av1", format: "" },
    { fetch_format: "mp4", video_codec: "h265", format: "" },
    { fetch_format: "mp4", video_codec: "h264", format: "" }  ]})
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.mp4", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webm").videoCodec("vp9").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("av1").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h265").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h264").format(""))));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.mp4"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().FetchFormat("webm").VideoCodec("vp9").Format(""),
   new EagerTransformation().FetchFormat("mp4").VideoCodec("av1").Format(""),
   new EagerTransformation().FetchFormat("mp4").VideoCodec("h265").Format(""),
   new EagerTransformation().FetchFormat("mp4").VideoCodec("h264").Format("")}};
var uploadResult = cloudinary.Upload(uploadParams);

|android
MediaManager.get().upload("sample.mp4")
  .option("eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webm").videoCodec("vp9").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("av1").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h265").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h264").format(""))).dispatch();

|swift
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setFetchFormat("webm").setVideoCodec("vp9").setFormat(""),
    CLDTransformation().setFetchFormat("mp4").setVideoCodec("av1").setFormat(""),
    CLDTransformation().setFetchFormat("mp4").setVideoCodec("h265").setFormat(""),
    CLDTransformation().setFetchFormat("mp4").setVideoCodec("h264").setFormat("")])
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.mp4", params: params)

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
      Eager: "vc_vp9/f_webm|vc_av1/f_mp4|vc_h265/f_mp4|vc_h264/f_mp4"})

|cli
cld uploader upload sample.mp4 eager='f_webm,vc_vp9/|f_mp4,vc_av1/|f_mp4,vc_h265/|f_mp4,vc_h264/'

|curl
curl https://api.cloudinary.com/v1_1/demo/video/upload -X POST --data 'file=sample.mp4&eager=f_webm,vc_vp9|f_mp4,vc_av1|f_mp4,vc_h265|f_mp4,vc_h264&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

> **NOTES**:
>
> * **Format parameter requirement**: If only the `fetch_format` parameter is specified, without the `format` parameter, then the URL is automatically generated with a file extension according to the format used when the eager transformation is generated. This results in URLs that differ both in the `f` parameter and the extension, so it would be impossible to specify one delivery URL using `f_auto` that would work for all of the eagerly generated transformations.  Thus providing the empty value for the `format` parameter is required.

> * **Including transformations**: If applying other transformations, you need to include those in your eager transformations too, including the default quality parameter that is applied automatically.

> * **Parameter order**: Be aware that the order of parameters is important - the request URL that you deliver must exactly match the eagerly generated URL. When using an upload preset or an SDK for the eager generation, parameters within a transformation component are alphabetized, for example, `f_mp4,q_auto,vc_h264`, or, for newer SDKs, split into different components, for example, `vc_h264/f_mp4/q_auto`.

> * **AV1 codec availability**: AV1 is a premium feature for Enterprise customers and may not be available for all account types. Availability depends on your account setup. To check if AV1 is available for your account or to discuss enabling it, [contact support](https://support.cloudinary.com/hc/en-us/requests/new).

### Eager asynchronous transformations

You can tell Cloudinary to generate eager transformations in the background by setting the `eager_async` parameter to `true`. This is useful when you use direct uploading from the browser and you don't want your users to have to wait for the transformation(s) to finish processing. In addition, you can set the optional `eager_notification_url` parameter to receive a webhook notification when the transformation generation is completed. For details, see [Notifications](notifications).

The `upload` method supports the following parameters for eager asynchronous transformations:

* `eager` - A list of transformations to create for the uploaded asset during the upload process, instead of lazily generating them when first accessed by your site's visitors. This option accepts either a single transformation or an array of transformations, where each transformation is represented by a hash of parameters. For details on available transformation parameters, see the [Transformation URL API Reference](transformation_reference). 
* `eager_async` - A Boolean value determining whether to generate the eager transformations asynchronously in the background after the file is finished uploading or synchronously as part of the upload call. Default: false.
* `eager_notification_url` - An HTTP or HTTPS URL to notify your application (a webhook) when the generation of eager transformations is completed. If a transformation fails for some reason, the response includes "state=failed" and the reason.

For example, the following method will upload the `sample.jpg` image and then eagerly generate two transformed images as follows: 

1. Pad to a width and height of 300 pixels.
2. Crop to a width of 160 pixels and a height of 100 pixels with south gravity. 

Furthermore, the transformations will be performed asynchronously after the file finishes uploading, with a callback URL to notify your application once the upload is complete and a different callback URL to notify your application once the transformations are complete:

```multi
|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  eager: [
    { width: 300, height: 300, crop: "pad"}, 
    { width: 160, height: 100, crop: "crop", gravity: "south"}], 
  eager_async: true, 
  eager_notification_url: "https://mysite.example.com/eager_endpoint",
  notification_url: "https://mysite.example.com/upload_endpoint")
 
|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
    "eager" => [
        ["width" => 300, "height" => 300, "crop" => "pad"],
        ["width" => 160, "height" => 100, "crop" => "crop", "gravity" => "south"]],
    "eager_async" => true,
    "eager_notification_url" => "https://mysite.example.com/eager_endpoint",
    "notification_url" => "https://mysite.example.com/upload_endpoint"]);
 
|python
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"width": 300, "height": 300, "crop": "pad"},
    {"width": 160, "height": 100, "crop": "crop", "gravity": "south"}],
  eager_async = True,
  eager_notification_url = "https://mysite.example.com/eager_endpoint",
  notification_url = "https://mysite.example.com/upload_endpoint")


|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { eager: [
      { width: 300, height: 300, crop: "pad" }, 
      { width: 160, height: 100, crop: "crop", gravity: "south"} ],                                   
    eager_async: true,
    eager_notification_url: "https://mysite.example.com/eager_endpoint",
    notification_url: "https://mysite.example.com/upload_endpoint" })
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().width(300).height(300).crop("pad"),
      new EagerTransformation().width(160).height(100).crop("crop").gravity("south")),
    "eager_async", true,
    "eager_notification_url", "https://mysite.example.com/eager_endpoint",
    "notification_url", "https://mysite.example.com/upload_endpoint"));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().Width(300).Height(300).Crop("pad"),
   new EagerTransformation().Width(160).Height(100).Crop("crop").Gravity("south")},
  EagerAsync = true,
  EagerNotificationUrl = "https://mysite.example.com/eager_endpoint",
  NotificationUrl = "https://mysite.example.com/upload_endpoint"};
var uploadResult = cloudinary.Upload(uploadParams);     

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
	Eager:                "c_scale,h_300,w_300/c_pad|c_scale,h_100,w_160/c_crop,g_south",
	EagerAsync:           api.Bool(true),
	EagerNotificationURL: "https://mysite.example.com/eager_endpoint",
	NotificationURL:      "https://mysite.example.com/upload_endpoint"})

|cli
cld uploader upload sample.jpg eager_async=true eager_notification_url='https://mysite.example.com/eager_endpoint' notification_url='https://mysite.example.com/upload_endpoint' eager='w_300,h_300,c_pad|w_160,h_100,c_crop,g_south'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&eager_async=true&eager_notification_url=https://mysite.example.com/eager_endpoint&notification_url=https://mysite.example.com/upload_endpoint&eager=w_300,h_300,c_pad|w_160,h_100,c_crop,g_south&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

#### Eager notification response

When the eager transformations are completed, an HTTP POST request will be sent to the eager notification webhook URL you provided, with details about the requested eager transformations including the HTTP and HTTPS URLs for accessing the derived assets. For example:

```json
{
  "notification_type":"eager", 
  "eager":[{
    "transformation":"jpg", 
    "width":190, 
    "height":100, 
    "bytes":1805410,
    "url":"http://res.cloudinary.com/demo/image/upload/h_100,w_190/v1517971772/qvd.jpg", 
    "secure_url":"https://res.cloudinary.com/demo/image/upload/h_100,w_190/v1517971772/qvd.jpg" }], 
    "batch_id":"6ebf1479dd8b71eb4e632620520f7347978a37ee7e30595a119c0efb957fb8c3ff96",
    "asset_id":"60b6169772654e3bc02f59e3577f5856",
    "public_id":"qvd" 
}
```

For more information on Eager notification URLs and responses, see the [Notifications](notifications) documentation.

  
## Incoming transformations

By default, assets uploaded to Cloudinary are stored as-is. During or after the upload, you can generate a variety of derived assets from these originals by asking Cloudinary to apply transformations.

In most cases, you'll probably want to store your originals without any changes. However, in some cases, you may want to modify the original assets before storing them by applying an **incoming** transformation as part of the upload request. Contrary to [eager transformations](#eager_transformations), incoming transformations are applied before storing the asset in Cloudinary. This is especially useful to normalize [user-generated content](user_generated_content), for example to limit the resolution size or clip a long video to a maximum duration.

You can specify any supported image or video transformation parameter for your incoming transformation using the `transformation` parameter. This parameter accepts either a single transformation or an array of transformations, where each transformation is represented by a hash of transformation parameters. 

For details on all available transformation parameters, see the [Transformation URL API Reference](transformation_reference).

> **NOTES**:
>
> * When using the SDK for a dynamically typed language, you can specify the transformation parameters directly, without explicitly specifying the `transformation` parameter, as seen in the example below for Node.js, Python, PHP, and Ruby.

> * To ensure that all file and layer data is completely preserved in your stored image, do not apply any [incoming transformations](eager_and_incoming_transformations#incoming_transformations) when uploading PSD, TIFF or other image formats containing layers.

For example, to limit the dimensions of an uploaded image to a width of 2000 pixels and a height of 1000 pixels:

```multi
|ruby
Cloudinary::Uploader.upload("sample.jpg", 
  width: 2000, height: 1000, crop: "limit")
   
|php_2
$cloudinary->uploadApi()->upload("sample.jpg", 
  ["width" => 2000, "height" => 1000, "crop" => "limit"]);

|python
cloudinary.uploader.upload("sample.jpg", 
  transformation = {"width": 2000, "height": 1000, "crop": "limit"})

|nodejs
cloudinary.v2.uploader
.upload("sample.jpg",
  { width: 2000, height: 1000, crop: "limit" })
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.jpg",
  ObjectUtils.asMap("transformation", 
    new Transformation().width(2000).height(1000).crop("limit")));

|csharp
var uploadParams = new ImageUploadParams() {
  File = new FileDescription(@"sample.jpg"),
  Transformation = new Transformation().Width(2000).Height(1000).Crop("limit")};
var uploadResult = cloudinary.Upload(uploadParams); 

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
		Transformation: "c_scale,h_1000,w_2000/c_limit"})

|android
MediaManager.get().upload("sample.jpg")
  .option("transformation", new Transformation().width(2000).height(1000).crop("limit")).dispatch();

|swift
let params = CLDUploadRequestParams()
  .setTransformation(
    CLDTransformation().setWidth(2000).setHeight(1000).setCrop("limit"))
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

|cli
cld uploader upload sample.jpg transformation='[{"width": 2000, "height": 1000, "crop": "limit"}]'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&transformation=w_2000,h_1000,c_limit&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```  

This example applies the named transformation "watermark" at the time of upload, which scales the image to a width of 600 pixels and overlays a Cloudinary logo:

```multi
|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  transformation: "watermark")

|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
  "transformation" => "watermark"]);

|python
cloudinary.uploader.upload("sample.jpg", 
  transformation = "watermark")

|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { transformation: "watermark" })
.then(result => console.log(result)); 

|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("transformation", "watermark"));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Transformation = new Transformation().NamedTransformation("watermark")};
var uploadResult = cloudinary.Upload(uploadParams);

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
      Transformation: "t_watermark"})

|android
MediaManager.get().upload("sample.jpg")
  .option("transformation", "watermark").dispatch();

|swift
let params = CLDUploadRequestParams()
  .setTransformation("watermark")
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

|cli
cld uploader upload sample.jpg transformation='t_watermark'

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&transformation=t_watermark&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'

```