Transformations on upload

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

  • Eager transformations: Generate transformed assets during the upload call so that those transformations will already be available for delivery before your users access them for the first time. These transformations are generated in addition to storing the original asset as is. This is especially useful for transformations that can take a while to generate.
  • Incoming transformations: Transform the original asset before storing it in your Cloudinary account. This can be useful for example to limit images to a maximum resolution or videos to a maximum duration.

Eager transformations

Cloudinary can either transform your assets on demand, when first accessed by your visitors as 'lazy transformations', or during the asset upload process as eager transformations. Eager transformations are generated in addition to storing the original asset as is and you can request multiple eager transformations during a single upload command.

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 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, transformations that perform AI analyses, or other asynchronous operations, such as those performed by some 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. Eager transformations are also useful in the case that you want to enable Strict Transformations for your account and limit access to dynamic URLs (for more information, see Control access to assets).

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 more details on available transformation parameters, see the Transformation URL API 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 (|). Chained transformations are separated with a slash (/). For example, the following eager value will generate two transformations: crop out a 400x400 region centered on the largest detected face and then scale down to a width and height of 50 pixels, and crop to a width and height of 30 pixels with south gravity:

Copy to clipboard
eager=c_crop,w_400,h_400,g_face/w_50,h_50,c_scale|w_30,h_30,c_crop,g_south

For more details, see Uploading with a direct call to the REST API.

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.
Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg",
  :eager => [
    {:width => 400, :height => 300, :crop => :pad}, 
    {:width => 260, :height => 200, :crop => :crop, :gravity => :north}])
PHP v1:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", [ 
  "eager" => [
    ["width" => 400, "height" => 300, "crop" => "pad"],
    ["width" => 260, "height" => 200, "crop" => "crop", "gravity" => "north"]]]);
PHP v2:
Copy to clipboard
$cloudinary->uploadApi()->upload("sample.jpg", [ 
  "eager" => [
    ["width" => 400, "height" => 300, "crop" => "pad"],
    ["width" => 260, "height" => 200, "crop" => "crop", "gravity" => "north"]]]);
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"width": 400, "height": 300, "crop": "pad"},
    {"width": 260, "height": 200, "crop": "crop", "gravity": "north"}])
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { eager: [
    { width: 400, height: 300, crop: "pad" }, 
    { width: 260, height: 200, crop: "crop", gravity: "north"} ]}, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
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"))));
.NET:
Copy to clipboard
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);
iOS:
Copy to clipboard
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)
Android:
Copy to clipboard
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();
CLI:
Copy to clipboard
cld uploader upload sample.jpg eager='w_400,h_300,c_pad|w_260,h_200,c_crop,g_north'

The delivery URLs for these eagerly generated transformations:

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :width=>400, :height=>300, :crop=>"pad")
PHP v1:
Copy to clipboard
cl_image_tag("sample.jpg", array("width"=>400, "height"=>300, "crop"=>"pad"))
PHP v2:
Copy to clipboard
(new ImageTag('sample.jpg'))
  ->resize(Resize::pad()->width(400)->height(300));
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(width=400, height=300, crop="pad")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {width: 400, height: 300, crop: "pad"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(400).height(300).crop("pad")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {width: 400, height: 300, crop: "pad"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {width: 400, height: 300, crop: "pad"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="400" height="300" crop="pad" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="400" height="300" crop="pad" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="400" height="300" crop="pad">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(400).Height(300).Crop("pad")).BuildImageTag("sample.jpg")
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(400).setHeight(300).setCrop("pad")).generate("sample.jpg")!, cloudinary: cloudinary)
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(400).height(300).crop("pad")).generate("sample.jpg");
Kotlin:
Copy to clipboard
cloudinary.image {
publicId("sample.jpg")
resize(Resize.pad() {
width(400)
height(300)
})}.generate()
sample.jpg padded to a width of 400 pixels and height of 300 pixels

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :width=>260, :height=>200, :gravity=>"north", :crop=>"crop")
PHP v1:
Copy to clipboard
cl_image_tag("sample.jpg", array("width"=>260, "height"=>200, "gravity"=>"north", "crop"=>"crop"))
PHP v2:
Copy to clipboard
(new ImageTag('sample.jpg'))
  ->resize(Resize::crop()->width(260)->height(200)
    ->gravity(Gravity::compass(Compass::north())));
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(width=260, height=200, gravity="north", crop="crop")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {width: 260, height: 200, gravity: "north", crop: "crop"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(260).height(200).gravity("north").crop("crop")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {width: 260, height: 200, gravity: "north", crop: "crop"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {width: 260, height: 200, gravity: "north", crop: "crop"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="260" height="200" gravity="north" crop="crop" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="260" height="200" gravity="north" crop="crop" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="260" height="200" gravity="north" crop="crop">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(260).Height(200).Gravity("north").Crop("crop")).BuildImageTag("sample.jpg")
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(260).setHeight(200).setGravity("north").setCrop("crop")).generate("sample.jpg")!, cloudinary: cloudinary)
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(260).height(200).gravity("north").crop("crop")).generate("sample.jpg");
Kotlin:
Copy to clipboard
cloudinary.image {
publicId("sample.jpg")
resize(Resize.crop() {
width(260)
height(200)
gravity(Gravity.compass(Compass.north()))
})}.generate()
sample.jpg cropped to a width of 260 pixels and a height of 200 pixels with north gravity

Note
When using the SDK for a dynamically-typed language, the transformation parameters can be specified directly, without specifying the transformation parameter, as seen for example in the examples for Ruby, PHP, Python, and Node.js above.

You can also generate eager transformations for previously uploaded assets using the explicit API method.

Using automatic format in eager transformations

Although it is possible to specify f_auto in an eager transformation, doing so does not eagerly generate derived assets for all formats, as the automatic format parameter is converted to the relevant formats at the CDN level based on the requesting browser. Therefore, to ensure you have all format variants available in advance, you need to eagerly generate every possible transformation that could replace 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:

Ruby:
Copy to clipboard
cl_image_tag("sample", :fetch_format=>:auto)
PHP v1:
Copy to clipboard
cl_image_tag("sample", array("fetch_format"=>"auto"))
PHP v2:
Copy to clipboard
(new ImageTag('sample'))
  ->delivery(Delivery::format(Format::auto()));
Python:
Copy to clipboard
CloudinaryImage("sample").image(fetch_format="auto")
Node.js:
Copy to clipboard
cloudinary.image("sample", {fetch_format: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().fetchFormat("auto")).imageTag("sample");
JS:
Copy to clipboard
cloudinary.imageTag('sample', {fetchFormat: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample", {fetch_format: "auto"})
React:
Copy to clipboard
<Image publicId="sample" >
  <Transformation fetchFormat="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample" >
  <cld-transformation fetchFormat="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample" >
  <cl-transformation fetch-format="auto">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().FetchFormat("auto")).BuildImageTag("sample")
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setFetchFormat("auto")).generate("sample")!, cloudinary: cloudinary)
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().fetchFormat("auto")).generate("sample");
Kotlin:
Copy to clipboard
cloudinary.image {
publicId("sample")
delivery(Delivery.format(Format.auto()))}.generate()

Thus, instead of generating an eager transformation with f_auto in the URL, you need to generate an eager transformation for each of f_wdp, f_jp2 and f_webp, while setting the format parameter (that controls the extension) to an empty string:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg",
  :eager => [
    {:fetch_format => :wdp, :format => :''},
    {:fetch_format => :jp2, :format => :''},
    {:fetch_format => :webp, :format => :''}])
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", [ 
  "eager" => [
    ["fetch_format" => "wdp", "format" => ""],
    ["fetch_format" => "jp2", "format" => ""],
    ["fetch_format" => "webp", "format" => ""]]]);
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  eager = [
    {"fetch_format": "wdp", "format": ""},
    {"fetch_format": "jp2", "format": ""},
    {"fetch_format": "webp", "format": ""}])
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { eager: [
    { fetch_format: "wdp", format: "" },
    { fetch_format: "jp2", format: "" },
    { fetch_format: "webp", format: "" } ]}, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("wdp").format(""),
      new EagerTransformation().fetchFormat("jp2").format(""),
      new EagerTransformation().fetchFormat("webp").format(""))));
.NET:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().FetchFormat("wdp").Format(""),
   new EagerTransformation().FetchFormat("jp2").Format(""),
   new EagerTransformation().FetchFormat("webp").Format("")}};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setFetchFormat("wdp").setFormat(""),
    CLDTransformation().setFetchFormat("jp2").setFormat(""),
    CLDTransformation().setFetchFormat("webp").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)
Android:
Copy to clipboard
MediaManager.get().upload("sample.jpg")
  .option("eager", Arrays.asList(
      new EagerTransformation().fetchFormat("wdp").format(""),
      new EagerTransformation().fetchFormat("jp2").format(""),
      new EagerTransformation().fetchFormat("webp").format(""))).dispatch();
CLI:
Copy to clipboard
cld uploader upload sample.jpg eager='f_wdp/|f_jp2/|f_webp/|f_webp,fl_awebp/'

Response:

Copy to clipboard
...
  "eager": [
    {
      "transformation": "f_wdp/",
      "width": 1920,
      "height": 1281,
      "bytes": 138211,
      "format": "wdp",
      "url": "http://res.cloudinary.com/demo/image/upload/f_wdp/v1608208001/sample",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/f_wdp/v1608208001/sample"
    },
    {
      "transformation": "f_jp2/",
      "width": 1920,
      "height": 1281,
      "bytes": 124551,
      "format": "jp2",
      "url": "http://res.cloudinary.com/demo/image/upload/f_jp2/v1608208001/sample",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/f_jp2/v1608208001/sample"
    },
    {
      "transformation": "f_webp/",
      "width": 1920,
      "height": 1281,
      "bytes": 137172,
      "format": "webp",
      "url": "http://res.cloudinary.com/demo/image/upload/f_webp/v1608208001/sample",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/f_webp/v1608208001/sample"
    }
  ]
...

For animated images, specify f_webp,fl_awebp:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("animation.gif",
  :eager => [
    {:fetch_format => :webp, :flags => :awebp, :format => :''}])
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("animation.gif", [ 
  "eager" => [
    ["fetch_format" => "webp", "flags" => "awebp", "format" => ""]]]);
Python:
Copy to clipboard
cloudinary.uploader.upload("animation.gif", 
  eager = [
    {"fetch_format": "webp", "flags": "awebp", "format": ""}])
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("animation.gif", 
  { eager: [
    { fetch_format: "webp", flags: "awebp", format: "" }  ]}, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("animation.gif", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webp").flags("awebp").format(""))));
.NET:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"animation.gif"),
  EagerTransforms = new List<Transformation>(){
   new EagerTransformation().FetchFormat("webp").Flags("awebp").Format("")}};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setEager([
    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: "animation.gif", params: params)
Android:
Copy to clipboard
MediaManager.get().upload("animation.gif")
  .option("eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webp").flags("awebp").format(""))).dispatch();
CLI:
Copy to clipboard
cld uploader upload animation.gif eager='f_webp,fl_awebp/'

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

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.mp4",
  :eager => [
    {:fetch_format => :webm, :video_codec => :vp9, :format => :''}, 
    {:fetch_format => :mp4, :video_codec => :h265, :format => :''},
    {:fetch_format => :mp4, :video_codec => :h264, :format => :''}])
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.mp4", [ 
  "eager" => [
    ["fetch_format" => "webm", "video_codec" => "vp9", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h265", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h264", "format" => ""]]]);
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.mp4", 
  eager = [
    {"fetch_format": "webm", "video_codec": "vp9", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h265", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h264", "format": ""}])
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.mp4", 
  { eager: [
    { fetch_format: "webm", video_codec: "vp9", format: "" }, 
    { fetch_format: "mp4", video_codec: "h265", format: "" },
    { fetch_format: "mp4", video_codec: "h264", format: "" }  ]}, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.mp4", 
  ObjectUtils.asMap(
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webm").videoCodec("vp9").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h265").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h264").format(""))));
.NET:
Copy to clipboard
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("h265").Format(""),
   new EagerTransformation().FetchFormat("mp4").VideoCodec("h264").Format("")}};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setEager([
    CLDTransformation().setFetchFormat("webm").setVideoCodec("vp9").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)
Android:
Copy to clipboard
MediaManager.get().upload("sample.mp4")
  .option("eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webm").videoCodec("vp9").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h265").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h264").format(""))).dispatch();
CLI:
Copy to clipboard
cld uploader upload sample.mp4 eager='f_webm,vc_vp9/|f_mp4,vc_h265/|f_mp4,vc_h264/'

Note

If only the fetch_format parameter is specified, and not the format parameter, then the extension automatically changes accordingly 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.

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.

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.
  • 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:

Ruby:
Copy to clipboard
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 v1:
Copy to clipboard
\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 v2:
Copy to clipboard
$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:
Copy to clipboard
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")
Node.js:
Copy to clipboard
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" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
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"));
.NET:
Copy to clipboard
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);
CLI:
Copy to clipboard
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'

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:

Copy to clipboard
{
  "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 documentation.

Incoming transformations

Assets uploaded to Cloudinary are stored in your account as-is, by default. During or after the upload, you can generate derived assets from these originals by asking Cloudinary to apply transformations.

However, in some cases, you may want to modify the original assets before storing them in your account, by applying an incoming transformation as part of the upload request. Any supported image or video transformation parameter can be specified for your incoming transformation. Contrary to eager transformations, incoming transformations are applied before saving the asset in your account. This is especially useful to normalize user-generated content, for example to limit the resolution size or clip a long video to a maximum duration.

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

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :width => 2000, :height => 1000, :crop => :limit)
PHP v1:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  ["width" => 2000, "height" => 1000, "crop" => "limit"]);
PHP v2:
Copy to clipboard
$cloudinary->uploadApi()->upload("sample.jpg", 
  ["width" => 2000, "height" => 1000, "crop" => "limit"]);
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  "width" = 2000, "height" = 1000, "crop" = "limit")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg",
  { width: 2000, height: 1000, crop: "limit" },
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg",
  ObjectUtils.asMap("transformation", 
    new Transformation().width(2000).height(1000).crop("limit")));
.NET:
Copy to clipboard
var uploadParams = new ImageUploadParams() {
  File = new FileDescription(@"sample.jpg"),
  Transformation = new Transformation().Width(2000).Height(1000).Crop("limit")};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
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)
Android:
Copy to clipboard
MediaManager.get().upload("sample.jpg")
  .option("transformation", new Transformation().width(2000).height(1000).crop("limit")).dispatch();
CLI:
Copy to clipboard
cld uploader upload sample.jpg transformation='[{"width": 2000, "height": 1000, "crop": "limit"}]'

Note
When using the SDK for a dynamically-typed language, the transformation parameters can be specified directly, without specifying the transformation parameter, as seen for example in the examples for Ruby, PHP, Python, and Node.js above.

✔️ Feedback sent!

Rate this page: