Uploading assets

Using Cloudinary's upload capabilities, you can upload media assets in bulk with a variety of options for customizing how they will be uploaded, including naming, whether to apply manually specified or automatically generated tags and metadata, whether to apply incoming transformations or other AI-based analysis of the uploaded assets, and more.

Cloudinary provides a secure and comprehensive API for easily uploading media files from server-side code, directly from the browser or from a mobile application. You can either upload using Cloudinary's REST API or one of Cloudinary's client libraries (SDKs), which wrap the upload API and simplify integration with web sites and mobile applications. Once uploaded, you can manage your assets using the Admin API and automatically deliver them, applying smart optimizations and transformations.

Tip
You can also manually upload assets using Cloudinary's DAM user interface or using one of Cloudinary's platform integrations, such as WordPress, Magento, Adobe CC graphic design apps, and more, enabling sophisticated asset management for large websites, eComerce stores and more. For details, see Uploading and storing assets in the Digital Asset Management guide and the Platform integration guides.

Related topics

Uploading assets to the cloud

Cloudinary signed uploads are performed over HTTPS using a secure protocol based on your account's cloud_name, api_key and api_secret parameters. Alternatively, you can implement an unsigned upload without an authentication signature.

While you can use the REST API directly within your custom code to implement signed uploads, it is simpler and recommended to use Cloudinary's server-side SDKs:

When using Cloudinary's SDKs for signed uploads, the cloud_name, api_key and api_secret are generally configured globally, but they can be provided with each upload call as well.

The Cloudinary upload method performs an authenticated upload API call over HTTPS:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload(file, options = {})
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload($file, $options = array());
Python:
Copy to clipboard
cloudinary.uploader.upload(file, **options)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload(file, options, callback);
Java:
Copy to clipboard
cloudinary.uploader().upload(Object file, Map options);
.Net:
Copy to clipboard
cloudinary.Upload(UploadParams params);
iOS:
Copy to clipboard
cloudinary.createUploader().signedUpload(url: file, params: params)

For example, uploading a local image file named sample.jpg:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
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)

Uploading is performed synchronously, and once finished, the uploaded asset is immediately available for transformation and delivery.

Note
For simplicity, many of the examples throughout this Media Upload Guide use image files. However, in the great majority of cases, the features demonstrated by these examples can be equally applied to video and raw files as well. For some special considerations for video and raw files, see Uploading video files and Uploading non-media files as raw files.

Public ID

Every asset uploaded to Cloudinary is assigned a unique identifier in the form of a Public ID, which is a URL-safe string that is used to reference the uploaded resource as well as for building dynamic delivery and transformation URLs. You can also browse and search resources by Public IDs in Cloudinary's Media Library web interface.

If you don't supply a Public ID in the upload API call, you will receive a randomly assigned Public ID in the response from the upload API call. A randomly generated public_id will look something like this: 8jsb1xofxdqamu2rzwt9q. The resulting delivery URL for such an asset would be something like:

https://res.cloudinary.com/demo/image/upload/8jsb1xofxdqamu2rzwt9q.jpg

You can set the public_id parameter when you upload an asset, which is useful when you want your delivery URLs to be more readable and SEO-friendly. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :public_id => "sample_id")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array("public_id" => "sample_id"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  public_id = "sample_id")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { public_id: "sample_id" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("public_id", "sample_id"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  PublicId = "sample_id"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setPublicId("sample_id")
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)

Note
The public ID value for images and videos asset types should not include the file extension. If you include a . character in a public ID, that simply becomes part of the ID itself. The format (extension) of a media asset is appended to the public_id when it is delivered. For example, if you specify myname.mp4 as the public_id, then the image would be delivered as myname.mp4.mp4.
For raw asset types only, the file extension should be specified as part of the public_id.
For more details on asset types, see Asset types.

Using the Public ID to organize media assets in folders

The Public ID can also be divided into folders for more structured delivery URLs. To do this programmatically, separate the elements in your Public ID string with slashes (/). For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :public_id => "my_folder/my_sub_folder/my_name")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array("public_id" => "my_folder/my_sub_folder/my_name"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  public_id = "my_folder/my_sub_folder/my_name")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { public_id: "my_folder/my_sub_folder/my_name" },
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("public_id", "my_folder/my_sub_folder/my_name"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  PublicId = "my_folder/my_sub_folder/my_name"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setPublicId("my_folder/my_sub_folder/my_name")
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)

This can also be done by splitting the Public ID into 2 parts and also specifying the folder parameter. Using the same example as above, but this time with the folder parameter:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :folder => "my_folder/my_sub_folder/", 
  :public_id => "my_name")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array(
    "folder" => "my_folder/my_sub_folder/", 
    "public_id" => "my_name"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  folder = "my_folder/my_sub_folder/", 
  public_id = "my_name")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { folder: "my_folder/my_sub_folder/", 
    public_id: "my_name" },
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "folder", "my_folder/my_sub_folder/", 
    "public_id", "my_name"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  PublicId = "my_name",
  Folder = "my_folder/my_sub_folder/"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setPublicId("my_name")
  .setFolder("my_folder/my_sub_folder/")
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)

Notes

  • You can also create folders in the Media Library UI.
  • You cannot use 'v' followed by numeric characters as the name of a folder.
  • For details on delivering Public IDs in a folder structure with or without versions, see Asset versions.

To tell Cloudinary to use the original name of the uploaded file as its public ID, include the use_filename parameter and set it to true. The file name will be normalized to include only URL-safe characters, and a set of random characters will also be appended to ensure the uniqueness of the Public ID. By also including the unique_filename parameter and setting it to false, you can tell Cloudinary not to attempt to make the Public ID unique, and just use the normalized file name. The following code example will upload the image file with the filename, sample_file.jpg and ensure that the Public ID of the asset is set to sample_file:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample_file.jpg", 
  :use_filename => true, 
  :unique_filename => false)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample_file.jpg", 
  array(
    "use_filename" => TRUE, 
    "unique_filename" => FALSE));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample_file.jpg", 
  "use_filename" = 1, 
  "unique_filename" = 0)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample_file.jpg",
  { use_filename: true, 
    unique_filename: false },
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample_file.jpg",
  ObjectUtils.asMap(
    "use_filename", "true", 
    "unique_filename", "false"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  UseFilename = true,
  UniqueFilename = false};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setUseFileName(true)
  .setUniqueFilename(false)
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)

Multiple derived assets created by transformations of an uploaded asset share the same Public ID as the original asset. They are further identified by the specific transformation that created them. For more information on transformations, see the image transformation and video transformation guides.

Note
The Public ID format supports all printable characters except for the following reserved characters: ? & # \ % < >. In addition, spaces and forward slashes (/) cannot be used as the first or last character of the Public ID.

File source options

Cloudinary supports uploading media files from various sources, including a local path, a remote HTTP or HTTPS URL, a private storage (S3 or Google Storage) URL, a base-64 data URI, an FTP URL, or a Google Cloud Storage URL.

Local path

You can upload an asset by specifying the local path of a media file. This option is only available when using Cloudinary's SDKs. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("/home/sample.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("/home/sample.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("/home/sample.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("/home/sample.jpg", 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("/home/sample.jpg", ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"/home/sample.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
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: "/home/sample.jpg")

HTTP or HTTPS URL

If your assets are already publicly available online, you can specify their remote HTTP or HTTPS URLs instead of uploading the actual file or file data. In this case, Cloudinary will retrieve the file from its remote URL and upload it directly to your Cloudinary account. This option allows for a much faster migration of your existing media files. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("https://www.example.com/sample.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("https://www.example.com/sample.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("https://www.example.com/sample.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("https://www.example.com/sample.jpg", 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("https://www.example.com/sample.jpg", 
  ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"https://www.example.com/sample.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);

Private storage URL

If you have existing media files in a private storage (Amazon S3 or Google Storage) bucket, you can upload files from a storage bucket URL.

Notes

  • You can also use your private storage bucket for lazy uploading using the auto-upload mapping functionality or for primary and backup storage.
  • When using your own backup storage, the backup location should not be touched or modified in any way. Additionally, no archiving policy should be enforced on that location (such as an archive policy to a glacier on S3 buckets).

To enable this option, your storage bucket must be whitelisted. This requires the following steps:

  1. Add an empty file to your bucket with your cloud name as the filename, under the following folder structure: .wellknown/cloudinary/<your_cloud_name>

    • By adding this file, you indicate that you have access to this bucket and that you permit Cloudinary to upload from this bucket to the specified cloud account.
    • If you want this bucket to be whitelisted for more than one Cloudinary account (or sub-account), you can add an appropriately named file for each cloud name.
  2. Provide Cloudinary with read access to your bucket:
    - How to set read access on a private Amazon S3 bucket
    - How to set read access on a Google Storage bucket

After your storage bucket is whitelisted, you can pass the Amazon S3 (s3://my-bucket/...) or Google Storage (gs://mybucket/...) URL in your upload method.

For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("s3://my-bucket/my-path/example.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("s3://my-bucket/my-path/example.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("s3://my-bucket/my-path/example.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("s3://my-bucket/my-path/example.jpg",
  function(error, result) { console.log(result); });
Java:
Copy to clipboard
cloudinary.uploader().upload("s3://my-bucket/my-path/example.jpg", 
  ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"s3://my-bucket/my-path/example.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);

How to set read access on a private Amazon S3 bucket
  1. In Amazon's AWS S3 Console, select the relevant bucket.
  2. In the Bucket Policy properties, paste the following policy text.
    Keep the Version value as shown below, but change BUCKETNAME to the name of your bucket.
    If a policy already exists, append this text to the existing policy:
Copy to clipboard
{
  "Version": "2012-10-17",
  "Id": "AWSConsole-AccessLogs-Policy-BUCKETNAME-cloudinary",
  "Statement": [
    {
      "Sid": "AWSConsoleStmt-BUCKETNAME-cloudinary",
       "Effect": "Allow",
       "Principal": {
         "AWS": "232482882421"
      },
       "Action": [
          "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::BUCKETNAME/*"
    }
  ]
}

Note
Amazon S3 bucket names containing a . character are not supported for this purpose.

How to set read access on a Google Storage bucket
  1. In your GCP console, go to your Google bucket's main page.
  2. Select to edit bucket permissions.
  3. Add service@cloudinary-gcs-production.iam.gserviceaccount.com as a member and give it the Storage Object Viewer role.

Base-64 Data URI

You can upload a file by specifying the Data URI of the file in base-64 encoding (no larger than 60 MB). For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
Python:
Copy to clipboard
cloudinary.uploader.upload("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
  ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==")};
var uploadResult = cloudinary.Upload(uploadParams);

FTP URL

You can upload a media file by specifying a remote FTP URL. For private FTP servers, the username and password must be included as parameters with the URL syntax taking the form: ftp://<user>:<password>@<host>:<port>/<url-path>. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("ftp://user1:mypass@ftp.example.com/sample.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("ftp://user1:mypass@ftp.example.com/sample.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("ftp://user1:mypass@ftp.example.com/sample.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("ftp://user1:mypass@ftp.example.com/sample.jpg", 
    function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("ftp://user1:mypass@ftp.example.com/sample.jpg", 
  ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"ftp://user1:mypass@ftp.example.com/sample.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);

Google Cloud Storage URL

You can upload a media file by specifying a remote Google Cloud Storage protocol (gs://). For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("gs://my_samples/sample.jpg")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("gs://my_samples/sample.jpg");
Python:
Copy to clipboard
cloudinary.uploader.upload("gs://my_samples/sample.jpg")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("gs://my_samples/sample.jpg", 
    function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("gs://my_samples/sample.jpg", 
  ObjectUtils.emptyMap());
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"gs://my_samples/sample.jpg")};
var uploadResult = cloudinary.Upload(uploadParams);

Asset types

Cloudinary supports many different file formats, which it categorizes into three different asset types (resource_type in the API):

The 'auto' resource_type

The upload method also supports supplying auto as a value for the resource_type parameter. When you send this value, Cloudinary automatically detects the asset type of the uploaded file and automatically sets the relevant resource_type value for the stored asset.

For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample_spreadsheet.xls", 
  :resource_type => :auto)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample_spreadsheet.xls", 
  array("resource_type" => "auto"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample_spreadsheet.xls", 
  resource_type = "auto")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample_spreadsheet.xls", 
  { resource_type: "auto" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample_spreadsheet.xls", 
  ObjectUtils.asMap("resource_type", "auto"));
.Net:
Copy to clipboard
var uploadResult = cloudinary.Upload("auto", null,
  new FileDescription(@"sample_spreadsheet.xls"));
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setResourceType(.auto)
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_spreadsheet.xls", params: params)

The auto value is especially useful when you don't know what type of files your users wlil upload, or if you are uploading multiple files of different asset types with the same settings. When using auto as the resource_type along with other upload options, only the upload options relevant to a particular asset type are be applied. Any options that work only with a different asset type are silently ignored.

Passing the resource_type parameter to your upload call

  • When uploading using the REST API, the resource_type is part of your upload endpoint.
  • When uploading using a server-side SDK, image is the default resource_type. When uploading video or raw file types, you must pass the resource_type option either with the value auto or with the relevant specific asset type.
  • When using direct image uploading from the browser, resource type is set to auto by default.

Note that for simplicity, many of the examples in this guide demonstrate uploading an image file. If you use these code examples as the basis for your own video or raw file uploads, don't forget to add the resource_type option.

Uploading videos

Uploading videos generally works the same and supports the same options as uploading images. However, When uploading videos, keep the following guidelines in mind:

  • The default value for the upload method resource_type is image, so you must set the resource_type parameter when uploading videos. You can set the resource_type parameter to auto to instruct Cloudinary to automatically detect the asset type, or you can set the parameter to video if you know in advance that you are uploading a video file. For more details, see The 'auto' resource_type.
  • By default, uploading is performed synchronously, and once finished, the uploaded video is immediately available for transformations and delivery. For videos larger than 60 MB, you will need to use chunked uploading.
  • There are also file-size limitations to transforming larger videos on-the-fly (40 MB for free plans, 100 MB for paid plans). Therefore, it's best practice to generate your video transformations eagerly on upload.

Here's a simple video upload example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload(file, 
  :resource_type => :video,
  : <optional_parameters...>)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload(file, 
  array(
    "resource_type" => "video", 
    "<optional_parameters...>"));
Python:
Copy to clipboard
cloudinary.uploader.upload(file, 
  resource_type = "video", 
  <optional_parameters...>)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload(file, 
  { resource_type: "video", 
    <optional_parameters...> },
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload(file, 
  ObjectUtils.asMap(
    "resource_type", "video", 
    "<optional_parameters...>"));
.Net:
Copy to clipboard
cloudinary.Upload(UploadParams params);
Endpoint:
Copy to clipboard
https://api.cloudinary.com/v1_1/<cloud_name>/video/upload

Audio files (such as MP3s) can also be uploaded as a video resource. Audio files are treated as video files without a visual element and thus are uploaded in the same way as videos, using video as the resource_type. For example, uploading a local audio file named audio_sample.mp3:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("audio_sample.mp3", 
  :resource_type => :video)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("audio_sample.mp3", 
  array("resource_type" => "video"));
Python:
Copy to clipboard
cloudinary.uploader.upload("audio_sample.mp3", 
  resource_type = "video")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("audio_sample.mp3", 
  { resource_type: "video" }
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("audio_sample.mp3", 
  ObjectUtils.asMap("resource_type", "video"));
.Net:
Copy to clipboard
var uploadParams = new VideoUploadParams(){
  File = new FileDescription(@"audio_sample.mp3")};
var uploadResult = cloudinary.Upload(uploadParams);

Tip
The Cloudinary Video Player provides a feature-rich and customizable interface to present your uploaded videos to your users and allows you to make use of functionality such as adaptive bitrate streaming and much more.

Uploading non-media files as raw files

Any file that is not an image or video file is treated as a 'raw' file. Raw files are stored as-is when uploaded to Cloudinary. No transformations on uploaded raw files are available. However, you can deliver your raw assets through a dynamic CDN URL in the same way you deliver image and video assets.

Note
Although the Public IDs of image and video files do not include the file's extension, Public IDs of raw files must include the original file's extension.

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample_spreadsheet.xls", 
  :resource_type => :raw)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample_spreadsheet.xls", 
  array("resource_type" => "raw"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample_spreadsheet.xls", 
  resource_type = "raw")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample_spreadsheet.xls", 
  { resource_type: "raw" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample_spreadsheet.xls", 
  ObjectUtils.asMap("resource_type", "raw"));
.Net:
Copy to clipboard
var uploadParams = new RawUploadParams(){  // by default, ResourceType is already set to "raw"
  File = new FileDescription(@"sample_spreadsheet.xls")};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setResourceType(.raw)
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_spreadsheet.xls", params: params)

Here's a sample response of a raw upload call, which is slightly different from an image or video upload response:

Copy to clipboard
{
 "public_id": "sample_spreadsheet.xls",
 "version": 1371928603,
 "signature": "9088291a2c12202767cfa7c5e874afee72be78cd",
 "resource_type": "raw",
 "created_at": "2017-06-22T19:16:43Z",
 "tags": [],
 "bytes": 6144,
 "type": "upload",
 "etag": "107bf134b5afd11cc7544d60108d87b", 
 "url": "http://res.cloudinary.com/demo/raw/upload/v1371928603/sample_spreadsheet.xls",
 "secure_url": "https://res.cloudinary.com/demo/raw/upload/v1371928603/sample_spreadsheet.xls"
 "original_filename": "sample_spreadsheet"
}
Converting raw files

The raw_convert upload parameter enables you to perform certain asynchronous operations on uploaded files. Depending on the option specified for this parameter, you can either convert certain raw files to other formats or generate related raw files that can be used in conjunction with the image or video file you uploaded.

For example:

  • Specify aspose as the value for your raw_convert parameter when uploading an Office document to instruct the Aspose Document Conversion add-on to generate a PDF image file from your raw office document.
  • Specify google_speech when uploading a video to instruct the Google AI Video Transcription add-on to generate an automatic transcript raw file from your uploaded video.
  • Specify extract_text when uploading a PDF file to extract all the text from the PDF file and store it in a raw file. The public ID of the generated file will be in the format: [pdf_public_id].extract_text.json.

    Note
    The text extraction result using the extract_text option may be different than the result you get if you use the OCR text detection and extraction add-on. For example, the OCR add-on includes exact coordinates of each line of text. Additionally, if your PDF contains images with text, the OCR add-on will capture this text, but the raw_convert:"extract_text" option will not.

Asset versions

When you upload a new media asset while specifying its public_id to be the same as an existing asset, your Cloudinary account will be updated with the new image or video, overwriting the old one. However, if the original (older) asset has already been accessed, it might already be cached in the CDN. If an end-user accesses the exact same URL soon after you overwrote the asset, they will still be accessing a CDN cached version rather than the new updated one.

The version component is an optional part of the delivery URL that can be added in order to bypass the CDN cached version and force delivery of the newest asset. Cloudinary returns the value of the version parameter as part of every upload response, and the returned url and secure_url parameters also include the version component, which represents the timestamp of the upload. For example:

Example image delivery URL without version:

https://res.cloudinary.com/demo/image/upload/sample.jpg

Example image delivery URL with version:

https://res.cloudinary.com/demo/image/upload/v1371750447/sample.jpg

As an alternative to using versions, you can set the invalidate parameter to true while uploading a new asset in order to invalidate the previous media asset throughout the CDN. It usually takes between a few seconds and a few minutes for the invalidation to fully propagate through the CDN, while the version component takes effect immediately.

Notes

  • You cannot use 'v' followed by numeric characters as the name of a folder.
  • There are also a number of other important considerations when using the invalidate functionality. For example, if there is no version number in a URL that includes a folder structure, then by default, those URLs are not invalidated. For details on invalidating media assets, see Invalidating cached media assets on the CDN.

Chunked asset upload

In order to support the upload of large files, the Cloudinary SDKs include a method which offers a degree of tolerance for network issues. The upload_large method uploads a large file to the cloud in chunks, and is required for any files that are larger than 100 MB. This is often relevant for video files, as they tend to have larger files sizes.

Note
The upload_large method is supported only in the Cloudinary SDKs. When directly calling the REST API, you can make use of the byte Content-Range entity-header HTTP specification to send the file in multiple calls.

By default, when using the upload_large method, files are uploaded as raw files if the resource_type parameter is not specified. For more details about the resource_type option, see Asset types

For example, uploading a large video file named my_large_video.mp4:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload_large("my_large_video.mp4", 
    :resource_type => "video")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload_large("my_large_video.mp4",
  array("resource_type" => "video"));
Python:
Copy to clipboard
cloudinary.uploader.upload_large("my_large_video.mp4", 
  resource_type = "video")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload_large("my_large_video.mp4", 
  { resource_type: "video" },
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().uploadLarge("my_large_video.mp4",
  ObjectUtils.asMap("resource_type", "video"));
.Net:
Copy to clipboard
var uploadParams = new VideoUploadParams(){ // This class sets the resource type to Video
  File = new FileDescription(@"my_large_video.mp4")};
var uploadResult = cloudinary.UploadLarge(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setResourseType("video")
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().signedUploadLarge(
  url: "my_large_video.mp4", params: params)

By default, the chunk size is set to 20 Megabytes but can be set to as low as 5 Megabytes by using the chunk_size parameter. For example, uploading a large video file named my_large_video.mp4 and setting chunk size to 6 Megabytes:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload_large("my_large_video.mp4",
  :resource_type => "video", 
  :chunk_size => 6_000_000)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload_large("my_large_video.mp4", 
  array(
    "resource_type" => "video", 
    "chunk_size" => 6000000));
Python:
Copy to clipboard
cloudinary.uploader.upload_large("my_large_video.mp4", 
  resource_type = "video", 
  chunk_size = 6000000)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload_large("my_large_video.mp4", 
  { resource_type: "video", 
    chunk_size: 6000000 }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().uploadLarge("my_large_video.mp4",
  ObjectUtils.asMap(
    "resource_type", "video", 
    "chunk_size", 6000000));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){ // This class sets the resource type to Video
  File = new FileDescription(@"my_large_video.mp4"),
  ChunkSize = 6000000};
var uploadResult = cloudinary.UploadLarge(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setResourseType("video")
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().signedUploadLarge(
  url: "my_large_video.mp4", params: params, chunkSize: 6000000)

Upload response

An upload API call returns a response that includes the HTTP and HTTPS URLs for accessing the uploaded file, as well as additional information regarding the uploaded asset. Among these are the assigned Public ID and current version of the asset (used in the Media Library, Admin API, and for building transformation and delivery URLs), the asset's dimensions, the file format and a signature for verifying the response. The following is an example of the JSON response returned:

Copy to clipboard
{
 public_id: 'sample',
 version: '1312461204',
 width: 864,
 height: 564,
 format: 'jpg',
 created_at: '2017-08-10T09:55:32Z',
 resource_type: 'image',
 tags: [], 
 bytes: 9597, 
 type: 'upload', 
 etag: 'd1ac0ee70a9a36b14887aca7f7211737', 
 url: 'http://res.cloudinary.com/demo/image/upload/v1312461204/sample.jpg',
 secure_url: 'https://res.cloudinary.com/demo/image/upload/v1312461204/sample.jpg',
 signature: 'abcdefgc024acceb1c1baa8dca46717137fa5ae0c3',
 original_filename: 'sample'
}

Verifying signatures in the JSON response

Cloudinary adds a signature value in the JSON response to various API methods. You can then compare the returned signature value in the JSON response with the value of a signature generated on your server-side.

The signature is a hexadecimal message digest (hash value) created with the SHA-1 or SHA-256 (Secure Hash Algorithm) cryptographic function on the following parameters: public_id, version and api_secret.

Note
By default, SHA-1 digest is used to create and verify all Cloudinary signatures. To instead use the SHA-256 digest for all your account signatures, submit a request.

Use the Cloudinary SDK's api_sign_request method to generate a signature on your back-end for comparison purposes.

Ruby:
Copy to clipboard
Cloudinary::Utils.api_sign_request(params_to_sign, api_secret)
PHP:
Copy to clipboard
\Cloudinary::api_sign_request($params_to_sign, $api_secret)
Python:
Copy to clipboard
cloudinary.utils.api_sign_request(params_to_sign, api_secret)
Node.js:
Copy to clipboard
cloudinary.utils.api_sign_request(params_to_sign, api_secret)
Java:
Copy to clipboard
cloudinary.apiSignRequest(Map<String, Object> paramsToSign, String apiSecret)
.Net:
Copy to clipboard
cloudinary.Api.SignParameters(IDictionary<string, object> parameters)

For example, the signature for the asset with a public_id of "sample" and a version of "1312461204":

Ruby:
Copy to clipboard
Cloudinary::Utils.api_sign_request(
  array(
    public_id: "sample", 
    version: "1312461204"), 
  "my_api_secret")
PHP:
Copy to clipboard
\Cloudinary::api_sign_request(
  array("public_id" => "sample", "version" => "1312461204"), "my_api_secret")
Python:
Copy to clipboard
cloudinary.utils.api_sign_request(
  dict(public_id: "sample", version: "1312461204"), "my_api_secret")
Node.js:
Copy to clipboard
cloudinary.utils.api_sign_request(
  {public_id: "sample", version: "1312461204"}, "my_api_secret")
Java:
Copy to clipboard
cloudinary.apiSignRequest(
  ObjectUtils.asMap(
    "publicId", "sample", 
    "version", "1312461204"),
  "my_api_secret")
.Net:
Copy to clipboard
var checkParams = new SortedDictionary<string, object>();
checkParams.Add("public_id", "sample");
checkParams.Add("version", "1312461204");
string expectedSign = cloudinary.Api.SignParameters(checkParams);

Manually verifying a signature

You can manually generate the comparison signature instead of using the Cloudinary SDK's api_sign_request method.

  1. Create a string with the public_id and version parameters, in that order. Separate the parameter names from their values with an = and join the parameter/value pairs together with an &.
  2. Append your API secret to the end of the string.
  3. Create a hexadecimal message digest (hash value) of the string using the SHA-1 function.

For example, if the asset has a public_id of "sample", a version of "1315060510", and your API secret is abcd:

  • Parameters to sign:
    • public_id: sample
    • version: 1315060510
  • Serialized sorted parameters in a single string:
    • public_id=sample&version=1315060510
  • String including the API secret that is used to create the SHA-1 signature:
    • public_id=sample&version=1315060510abcd
  • SHA-1 hexadecimal result:
    • b4ad47fb4e25c7bf5f92a20089f9db59bc302313

An example of the above in Ruby on Rails:

Copy to clipboard
public_id = "sample"
version = "1315060510"
secret = "abcd"

to_sign = 'public_id=' + public_id + '&' + 'version=' + version
signature = Base64.urlsafe_encode64(Digest::SHA1.digest(to_sign + secret))

Control access to assets

By default, when uploading assets to Cloudinary, both the original asset and its transformed versions are publicly available through a CDN. You can use random Public IDs to make it harder to guess asset URLs (Cloudinary's default behavior if no Public ID is specified), but you might still want further access control.

This section shows how to apply these access control features as part of your upload command. For more information on all of these features and how they impact user acess upon delivery, see Media access control.

Private assets

You can upload assets as private to restrict access to the original asset and only allow access to derived (transformed) versions of the asset. The original asset can be accessed only with a signed URL, but by default, all derived versions of the asset are accessible. You can further restrict access to the derived asset by activating the Strict Transformations mode. This mode also prevents access to the derived versions of the asset, except for those that have been specifically enabled (e.g., with watermarks) that are then available for public delivery to your users. With Strict Transformations enabled, you need to either eagerly generate all derived assets, mark specific transformations as allowed or use signed URLs.

To upload an asset as a private asset, you set the type parameter to private (instead of the default upload) when uploading the asset to Cloudinary. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :type => :private)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array("type" => "private"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  type = "private")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { type: "private" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("type", "private"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Type = "private"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setType(.private)
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)

An asset that was uploaded as ‘private’ cannot be accessed publicly without a signed URL. For example, the following URL returns an error:

https://res.cloudinary.com/demo/image/private/sample.jpg

Note
You can make a private original asset temporarily accessible, for example, to enable a customer to access a stock photo on your site after she purchases it. To do this, you need to deliver a time-limited and signed URL. You can do this directly using the API or you can use the private_download_url Utils method, which generates a time-limited, signed URL link to the original asset, which you can then provide to relevant customers. For details, see Providing time-limited access to private assets

Authenticated assets

You can upload assets as authenticated to even further restrict access to both the original asset and to the derived (transformed) versions of the asset. Authenticated assets and their derived versions cannot be accessed without some form of authentication. For more information see Authenticated access to media assets.

To upload an asset as an authenticated asset, you set the delivery type (type parameter) to authenticated (instead of the default upload) when uploading the asset to Cloudinary. For example:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :type => :authenticated)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array("type" => "authenticated"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  type = "authenticated")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { type: "authenticated" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("type", "authenticated"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Type = "authenticated"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setType(.authenticated)
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)

If an asset was uploaded as ‘authenticated’, neither the asset nor any of its derived resources can be accessed without authentication. For example, the following URL returns an error:

https://res.cloudinary.com/demo/image/authenticated/sample.jpg

Access mode

The access_mode parameter allows a resource with the delivery type upload to behave as if it's of type 'authenticated' while still using the default upload delivery type in URLs. The asset can later be made public by changing its access_mode via the Admin API, without having to update any delivery URLs. Valid values for the access_mode parameter include public (default) and authenticated.

For example, to upload the 'sample' image and set its access_mode as authenticated:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg", 
  :access_mode => :authenticated)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array("access_mode" => "authenticated"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  access_mode = "authenticated")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { access_mode: "authenticated" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap("access_mode", "authenticated"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams() {
  File = new FileDescription(@"sample.jpg"),
  AccessMode = "authenticated"};
var uploadResult = cloudinary.Upload(uploadParams);

Direct uploading from the browser

The upload samples shown above allow your code to upload files to Cloudinary. In this flow, if you have a web form that allows your users to upload media files, the file data is first sent to your server and only then uploaded to Cloudinary.

A more efficient and powerful option is to allow your users to upload assets directly from the browser or a mobile application instead of going through your servers. This method allows for faster uploading and better user experience for your visitors. It also reduces load from your servers and reduces the complexity of your applications.

One option for directly uploading from the browser is enabled by Cloudinary's jQuery plugin, which requires a small setup: including jQuery, Cloudinary's jQuery plugin, jQuery-File-Upload plugin files and defining your cloud name and API Key. For more information on direct uploading from the browser see the relevant SDK integration guide and the blog post on Direct upload made easy, from browser or mobile app to the cloud.

Activate signed client-side asset uploading by embedding an upload input field in your HTML pages. The Cloudinary SDKs have helper methods (e.g., the cl_image_upload_tag method) that automatically add a file input field to your form. Selecting or dragging a file to this input field will automatically initiate uploading from the browser to Cloudinary. For example, using Ruby on Rails (other frameworks use the same concept):

Copy to clipboard
cl_image_upload_tag(:image_id, options = {})

When uploading is completed, the identifier of the uploaded asset is set as the value of the given input field in your HTML page (the image_id parameter in the example above). You can then process the identifier received by your controller and store it for future use, exactly as if you're using standard server side uploading.

Note
If you manually create your own file input field (i.e., you don't use one of Cloudinary's helper methods), make sure to include the name="file" attribute in the input field (e.g., <input id="upload-img" type="file" name="file">)

Unsigned upload

Unsigned upload is an option for performing upload directly from a browser or mobile application with no authentication signature, and without going through your servers at all. However, for security reasons, not all upload parameters can be specified directly when performing unsigned upload calls.

Unsigned upload options are controlled by an upload preset, so in order to use this feature you first need to enable unsigned uploading for your Cloudinary account from the Upload Settings page. Enabling unsigned uploading also creates an upload preset with a unique name, which explicitly allows uploading of assets without authentication. The preset is also used to define which upload options will be applied to assets that are uploaded unsigned with that preset specified. You can edit the preset at any point in time (or create additional upload presets), to define the parameters that will be used for all assets that are uploaded unsigned from user browsers or mobile applications.

For more information on upload presets, see the upload preset documentation and the Centralized control for image upload blog post.

To perform an unsigned upload, call the unsigned_upload method of the Cloudinary SDKs while setting the upload_preset and cloud_name parameters. For example, to upload the sample.jpg file to the Cloudinary demo account with the unsigned_1 upload preset:

Ruby:
Copy to clipboard
Cloudinary::Uploader.unsigned_upload("sample.jpg", "unsigned_1", 
  :cloud_name => "demo")
PHP:
Copy to clipboard
\Cloudinary\Uploader::unsigned_upload("sample.jpg", "unsigned_1", 
  array("cloud_name" => "demo"));
Python:
Copy to clipboard
cloudinary.uploader.unsigned_upload("sample.jpg", "unsigned_1", 
  cloud_name = 'demo')
Node.js:
Copy to clipboard
cloudinary.v2.uploader.unsigned_upload("sample.jpg", "unsigned_1", 
  { cloud_name: "demo" }, 
  function(error, result) {console.log(result, error) });
Java:
Copy to clipboard
cloudinary.uploader().unsignedUpload("sample.jpg", "unsigned_1",
  ObjectUtils.asMap("cloud_name", "demo"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Unsigned = true,
  UploadPreset = "unsigned_1",
  CloudName = "demo"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let request = cloudinary.createUploader().upload(
  url: "sample.jpg", uploadPreset: "unsigned_1")

Note
For security reasons, only this restricted set of parameters can be used in an unsigned upload request. However, most upload parameters can be defined as part of your unsigned upload preset.

Upload multiple assets

The file input field can be configured to support multiple file uploading simultaneously by setting the multiple HTML parameter to true. You should manually bind to the cloudinarydone event to handle the results of multiple uploads. Here's an example:

Ruby:
Copy to clipboard
<%= cl_image_upload_tag(:image_id, 
  :html => { :multiple => true }) %>
PHP:
Copy to clipboard
<?php echo cl_image_upload_tag("image_id", 
  array("html" => array("multiple" => TRUE ))); ?>
Python:
Copy to clipboard
image = CloudinaryJsFileField(
  attrs = { 'multiple': 1 })
Node.js:
Copy to clipboard
cloudinary.uploader.image_upload_tag(
  'image_id', { html: { multiple: 1 } });
Java:
Copy to clipboard
String html = cloudinary.uploader().imageUploadTag("image_id", 
  ObjectUtils.asMap("multiple", true));

Display preview thumbnails and indicate upload progress

Cloudinary's jQuery library also enables an enhanced uploading experience - show a progress bar, display a thumbnail of the uploaded file, drag & drop support and more.

Bind to Cloudinary's cloudinarydone event if you want to be notified when an upload to Cloudinary has completed. You will have access to the full details of the uploaded asset and you can display a cloud-generated thumbnail of the uploaded assets using Cloudinary's jQuery plugin.

The following sample code creates a 150x100 thumbnail of an uploaded image and updates an input field with the Public ID of this image.

Copy to clipboard
$('.cloudinary-fileupload').bind('cloudinarydone', function(e, data) {  
  $('.preview').html(
    $.cloudinary.image(data.result.public_id, 
      { format: data.result.format, version: data.result.version, 
        crop: 'fill', width: 150, height: 100 })
  );    
  $('.image_public_id').val(data.result.public_id);    
  return true;
});

You can track the upload progress by binding to the following events: fileuploadsend, fileuploadprogress, fileuploaddone and fileuploadfail. You can find more details and options in the documentation of jQuery-File-Upload.

The following JavaScript code updates a progress bar according to the data of the fileuploadprogress event:

Copy to clipboard
$('.cloudinary-fileupload').bind('fileuploadprogress', function(e, data) { 
  $('.progress_bar').css('width', Math.round((data.loaded * 100.0) / data.total) + '%'); 
});

You can find some more examples as well as an upload button style customization in our Photo Album sample project.

For more details about direct uploading, see the following blog posts: Direct image uploads from the browser to the cloud with jQuery and Direct upload made easy, from browser or mobile app to the cloud

Deleting client-side uploaded assets

The Cloudinary jQuery library supports using a delete token to delete assets on the client-side for a limited time of 10 minutes after being uploaded. After 10 minutes have passed, the image cannot be deleted from the client side, only via the Destroy method of the Upload API or using the delete_resources method of the Admin API.

In order to also receive a deletion token in the upload response, add the return_delete_token parameter to the upload method and set it to true. This parameter is not supported when using unsigned uploads (although it can be set within the upload preset for the unsigned upload).

For example:

Ruby:
Copy to clipboard
<%= cl_image_upload_tag(:image_id, 
  :return_delete_token => true) %>
PHP:
Copy to clipboard
<?php echo cl_image_upload_tag("image_id", 
  array("return_delete_token" => TRUE )); ?>
Python:
Copy to clipboard
image = CloudinaryJsFileField(
  options = { 'return_delete_token': 1 })
Node.js:
Copy to clipboard
cloudinary.uploader.image_upload_tag('image_id', 
  { return_delete_token: 1 });
Java:
Copy to clipboard
String html = cloudinary.uploader().imageUploadTag(
  "image_id", ObjectUtils.asMap("return_delete_token", true));
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setReturnDeleteToken(true)
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)

The delete_token returned in the upload response can be used to delete the uploaded asset using the delete_by_token method of the jQuery SDK. For example:

Copy to clipboard
$.cloudinary.delete_by_token(delete_token)

Alternatively, you can access the delete_by_token endpoint directly with a POST request. For example:

Copy to clipboard
curl https://api.cloudinary.com/v1_1/demo/delete_by_token -X POST --data 'token=delete_token'

Upload widget

Cloudinary's upload widget is an interactive, feature rich, simple to integrate method to allow your users to upload media files directly to Cloudinary. The widget eliminates the hassle of developing an in-house interactive file upload solution.

Cloudinary's upload widget includes a complete graphical interface and allows your website visitors to upload files from multiple sources. For example, one or more local files, a remote file (URL) or just snapping a photo directly from the computer or mobile device's camera. The widget supports drag & drop functionality, interactive cropping, upload progress indication and thumbnail previews, and also monitors and handles uploading errors. The upload widget's behavior can be configured and the look & feel can be customized.

Upload widget main screen

Cloudinary's upload widget requires pure Javascript to integrate and is easy to use with any web development framework. Advanced features are also available when using jQuery.

Integrating the widget in your site is very simple. Firstly, include the remote Javascript file of the upload widget:

Copy to clipboard
<script src="//widget.cloudinary.com/global/all.js" type="text/javascript"></script>

The upload widget can now be opened programmatically with, for example, the cloudinary.openUploadWidget method:

Copy to clipboard
<script type="text/javascript">  
  cloudinary.openUploadWidget({ cloud_name: 'demo', upload_preset: 'a5vxnzbp'}, 
    function(error, result) { console.log(error, result) });
</script>

For more information and specific details, including the parameters used in the openUploadWidget method, see the Upload Widget documentation.

Uploading with a direct call to the REST API

Cloudinary's client libraries (SDKs) wrap the Upload API and greatly simplify using the API methods (see the Upload API reference documentation for more information on all the Upload API's methods). Nevertheless, if you wish to upload files with a direct call to the API from within your own custom code you can send an HTTPS POST request to the following Cloudinary URL:

https://api.cloudinary.com/v1_1/<cloud name>/<resource_type>/upload

Where:

  • cloud name is the name of your Cloudinary account.
  • resource_type is the type of file to upload. Valid values: image, raw, video and auto to automatically detect the file type.

For example, to upload an image file to the Cloudinary 'demo' account, send an HTTPS POST request to the following URL:

https://api.cloudinary.com/v1_1/demo/image/upload

The contents of the POST request you send to Cloudinary depends on whether or not you are making an authenticated request (see the documentation on Unsigned uploads for more information on unauthenticated requests).

Required parameters for authenticated requests:

  • file - The file to upload. Can be the actual data (byte array buffer), the Data URI (Base64 encoded), a remote FTP, HTTP or HTTPS URL of an existing file, or a private storage bucket (S3 or Google Storage) URL of a whitelisted bucket.
  • api_key - The unique API Key of your Cloudinary account.
  • timestamp - Unix time in seconds of the current time (e.g., 1315060076).
  • signature - A signature of all request parameters including the 'timestamp' parameter but excluding the 'api_key', 'resource_type', 'cloud_name' and 'file' parameters, based on the API Secret of your Cloudinary account. The signature is valid for 1 hour. See Generating authentication signatures for more details.

Required parameters for unauthenticated requests:

  • file - The file to upload. Can be the actual data (byte array buffer), the Data URI (Base64 encoded), a remote FTP, HTTP or HTTPS URL of an existing file, or a private storage bucket (S3 or Google Storage) URL of a whitelisted bucket.
  • upload_preset - The name of an unsigned upload preset that you defined for unsigned uploading to your Cloudinary account.

Optional parameters:

See the Upload method of the API for all parameters available for uploading files.

Note
Unauthenticated requests are restricted to the following optional upload parameters:
public_id, folder, callback, tags, context, face_coordinates, custom_coordinates.
Additional upload parameters can be defined within your upload preset.

Generating authentication signatures

When using the Cloudinary SDKs, the signature is automatically generated and added to the request for any upload or admin method that requires signatures.

If you manually generate your own POST request, you need to authenticate the request with a signature based on the parameters you use in the request. The signature is a hexadecimal message digest (hash value) created with the SHA-1 or SHA-256 (Secure Hash Algorithm) cryptographic function.

Note
By default, SHA-1 digest is used to create and verify all Cloudinary signatures. To instead use the SHA-256 digest for all your account signatures, submit a request.

  1. Create a string with the parameters used in the POST request to Cloudinary:
    • All parameters added to the method call should be included except: file, cloud_name, resource_type and your api_key.
    • Add the timestamp parameter.
    • Sort all the parameters in alphabetical order.
    • Separate the parameter names from their values with an = and join the parameter/value pairs together with an &.
  2. Append your API secret to the end of the string.
  3. Create a hexadecimal message digest (hash value) of the string using SHA-1 (or SHA-256 if relevant for your account).

For example, if your API secret is abcd, your API key is 1234, the Unix time now is 1315060510 and you are posting a request to upload a file from 'https://www.example.com/sample.jpg', set its Public ID as sample_image, and eagerly generate 2 images:

  • Parameters to sign:
    • timestamp: 1315060510
    • public_id: sample_image
    • eager: w_400,h_300,c_pad|w_260,h_200,c_crop
  • Serialized sorted parameters in a single string:
    • eager=w_400,h_300,c_pad|w_260,h_200,c_crop&public_id=sample_image&timestamp=1315060510
  • String including the API secret that is used to create the SHA-1 signature:
    • eager=w_400,h_300,c_pad|w_260,h_200,c_crop&public_id=sample_image&timestamp=1315060510abcd
  • SHA-1 hexadecimal result:
    • bfd09f95f331f558cbd1320e67aa8d488770583e

The final request parameters for the upload POST request:

  • timestamp: 1315060510
  • public_id: sample_image
  • api_key: 1234
  • eager: w_400,h_300,c_pad|w_260,h_200,c_crop
  • file: https://www.example.com/sample.jpg
  • signature: bfd09f95f331f558cbd1320e67aa8d488770583e

For example, combining all the parameters in a cURL POST request to the demo account:

Copy to clipboard
curl -d "file=https://www.example.com/sample.jpg&api_key=1234&eager=w_400,h_300,c_pad|w_260,h_200,c_crop&public_id=sample_image&timestamp=1315060510&signature=bfd09f95f331f558cbd1320e67aa8d488770583e" -X POST http://api.cloudinary.com/v1_1/demo/image/upload

You can watch a video showing how to generate a signature using Node.js that uses the same parameters to sign as in the above example.

See also
Have a look a the Cloudinary Signatures quick reference for a summary of the payload string to sign for authentication signatures as well as information on other use cases that may require signature generation.

Using Cloudinary server-side SDKs to generate authentication signatures

You can use the relevant syntax below to generate the authentication signature using one of Cloudinary's server-side SDKs. Make sure that the timestamp is included in the params_to_sign object.

Ruby:
Copy to clipboard
Cloudinary::Utils.api_sign_request(params_to_sign, api_secret)
PHP:
Copy to clipboard
\Cloudinary::api_sign_request($params_to_sign, $api_secret);
Python:
Copy to clipboard
cloudinary.utils.api_sign_request(params_to_sign, api_secret)
Node.js:
Copy to clipboard
cloudinary.utils.api_sign_request(params_to_sign, api_secret);
Java:
Copy to clipboard
cloudinary.apiSignRequest(Map<String, Object> paramsToSign, String apiSecret);
.Net:
Copy to clipboard
cloudinary.Api.SignParameters(IDictionary<string, object> parameters);

Important considerations for authentication signatures

When generating authentication signatures keep in mind the following:

  • The api_secret, which is a required element of the signature, should never be revealed to anyone who is not authorized, and therefore your signature should never be generated on the client side or inside your native application.
  • For mobile and other client-side applications, you must either use unsigned upload or have a server for processing the signature.
  • Signatures are valid for one hour from the timestamp value used to generate the signature.
  • Make sure to regenerate the signature if you dynamically change the payload of an upload request.

See the Upload API reference for a list of API methods, parameters, and response samples.

Signed upload video tutorial

The following video shows an example of using the api_sign_request method from the Node.js library. This method generates a signature from the same parameters that were used in the example above for manually generating authentication signatures.

In the video, the code is run from the command line to show the timestamp and signature being generated for use in the POST request. In reality, this code would be in a function on your server, into which you would pass the parameters to sign and expect the signature and timestamp to be returned back to your client.

At the end of the example, a cURL command is built to upload https://upload.wikimedia.org/wikipedia/commons/b/b1/VAN_CAT.png to Cloudinary using a POST request to the upload API.

Here is the code from the video:

Copy to clipboard
const cloudinary = require('cloudinary').v2;
require('dotenv').config();

// Get the timestamp in seconds
var timestamp = Math.round((new Date).getTime()/1000);

// Show the timestamp
console.log('Timestamp:',timestamp);

// Get the signature using the Node.js SDK method api_sign_request
var signature = cloudinary.utils.api_sign_request({
    timestamp: timestamp,
    eager: 'w_400,h_300,c_pad|w_260,h_200,c_crop',
    public_id: 'sample_image'}, process.env.API_SECRET);

// Show the signature
console.log('Signature:', signature);

// ====================================================================================================

// Having got the timestamp and signature of the parameters to sign, we can now build the curl command.  

// URL of the file to upload
var file='https://upload.wikimedia.org/wikipedia/commons/b/b1/VAN_CAT.png';

// Build the curl command
var curl_command = 'curl -d "file=' + file + 
   '&api_key=323127161127519&eager=w_400,h_300,c_pad|w_260,h_200,c_crop&public_id=sample_image' + 
   '&timestamp=' + timestamp +
   '&signature=' + signature +
   '" -X POST http://api.cloudinary.com/v1_1/carl/image/upload';

// Show the curl command
console.log('curl command:', curl_command);

Error handling

Once the POST request is received and processed by Cloudinary, the Upload API returns the status of requests using one of the following HTTP status codes:

  • 200 - OK. Successful.
  • 400 - Bad request. Invalid request parameters.
  • 401 - Authorization required.
  • 403 - Not allowed.
  • 404 - Not found.
  • 420 - Rate limited.
  • 500 - Internal error. Contact support.

In the case of wrong usage of the API or an error, Cloudinary's response is returned with a non-OK (not 200) HTTP Status code and a body with the following JSON format:

Copy to clipboard
{ error: { message: "Something went wrong" } }

Uploading 3D models

You can upload a 3D model to your Cloudinary account by archiving all the needed 3D files into a single ZIP file, and then uploading that file to your Cloudinary account while specifying the resource_type as "image" (a ZIP file would normally be uploaded with a resource_type of "raw").

Cloudinary currently supports 3D models in the FBX and glTF formats that are uploaded as a single ZIP file, including any textures or other images used in the model. After exporting the 3D model in one of the supported formats to a new folder, zip the entire folder and then upload it to your Cloudinary account.

For example, to upload the 3D model archived in the sample_3D.zip file:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample_3D.zip", 
  :resource_type => :image)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample_3D.zip", 
  array("resource_type" => "image"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample_3D.zip", 
  resource_type = "image")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample_3D.zip", 
  { resource_type: "image" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample_3D.zip", 
  ObjectUtils.asMap("resource_type", "image"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){  // by default, ResourceType is already set to "image"
  File = new FileDescription(@"sample_3D.zip")};
var uploadResult = cloudinary.Upload(uploadParams);

Auto-fetching remote files

Auto-Upload and Fetch are two similar features for automatically fetching (retrieving) files from existing remote locations using dynamic URLs.

Fetch (supported for images only) enables on-the-fly manipulation of existing remote images and optimized delivery via a CDN. Fetched images are cached on your Cloudinary account for performance reasons. The remote images are checked on a regular basis, and if the remote image changes, the cached image is updated accordingly.

For example, to fetch a remote image of Jennifer Lawrence fetched by Cloudinary from WikiMedia:

Ruby:
Copy to clipboard
cl_image_tag("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg", :type=>"fetch")
PHP:
Copy to clipboard
cl_image_tag("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg", array("type"=>"fetch"))
Python:
Copy to clipboard
CloudinaryImage("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg").image(type="fetch")
Node.js:
Copy to clipboard
cloudinary.image("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg", {type: "fetch"})
Java:
Copy to clipboard
cloudinary.url().type("fetch").imageTag("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg', {type: "fetch"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg", {type: "fetch"})
React:
Copy to clipboard
<Image publicId="https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg" type="fetch">

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg" type="fetch">

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg" type="fetch">

</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Action("fetch").BuildImageTag("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg")
Android:
Copy to clipboard
MediaManager.get().url().type("fetch").generate("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setType( "fetch").generate("https://upload.wikimedia.org/wikipedia/commons/4/46/Jennifer_Lawrence_at_the_83rd_Academy_Awards.jpg")!, cloudinary: cloudinary)
Remote image retrieved and delivered using fetch

Auto Upload (supported for all media types) enables on-the-fly manipulation of existing remote media files and optimized delivery via a CDN, while simultaneously uploading the file to your Cloudinary account for further management, and thus benefiting from a variety of additional features (just like any other media file that was directly uploaded to your Cloudinary account). This feature is very useful for lazy migration of media assets from a remote location to your Cloudinary account with minimal effort on your side.

For example, if you create a folder called remote_media on your Cloudinary account and then map it to the URL prefix https://upload.wikimedia.org/wikipedia/, you can generate a Cloudinary delivery URL that substitutes the remote_media folder prefix for the URL prefix. Where the original URL is:

https://upload.wikimedia.org/wikipedia/commons/2/29/Marcelo_Facini.jpg

With the Auto Upload feature you would now access the following Cloudinary URL:

Ruby:
Copy to clipboard
cl_image_tag("remote_media/commons/2/29/Marcelo_Facini.jpg")
PHP:
Copy to clipboard
cl_image_tag("remote_media/commons/2/29/Marcelo_Facini.jpg")
Python:
Copy to clipboard
CloudinaryImage("remote_media/commons/2/29/Marcelo_Facini.jpg").image()
Node.js:
Copy to clipboard
cloudinary.image("remote_media/commons/2/29/Marcelo_Facini.jpg")
Java:
Copy to clipboard
cloudinary.url().imageTag("remote_media/commons/2/29/Marcelo_Facini.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('remote_media/commons/2/29/Marcelo_Facini.jpg').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("remote_media/commons/2/29/Marcelo_Facini.jpg")
React:
Copy to clipboard
<Image publicId="remote_media/commons/2/29/Marcelo_Facini.jpg" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="remote_media/commons/2/29/Marcelo_Facini.jpg" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="remote_media/commons/2/29/Marcelo_Facini.jpg" >

</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("remote_media/commons/2/29/Marcelo_Facini.jpg")
Android:
Copy to clipboard
MediaManager.get().url().generate("remote_media/commons/2/29/Marcelo_Facini.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("remote_media/commons/2/29/Marcelo_Facini.jpg")!, cloudinary: cloudinary)
Auto upload with remote_media folder mapped to https://upload.wikimedia.org/wikipedia/

The image is dynamically retrieved from WikiMedia the first time this URL is accessed and then it is uploaded and stored in your Cloudinary account just like any other uploaded asset with a Public ID of remote_media/commons/2/29/Marcelo_Facini.

For complete details on the Auto Upload and Fetch features, see Deliver remote media files.

Upload options

In addition to the basic programmatic upload functionality described on this page, the rest of the pages in this Upload guide describe a variety of valuable functionality that you can take advantage of while uploading assets.

  • Transformations on upload: While uploading an asset, you can perform eager transformations that will already be generated and available before your users access them for the first time. You can also perform incoming transformations, which transform the original asset before storing it in your account, for example to limit an image size or a video duration.
  • Analysis on upload: As part of your upload, you can request to perform one or more analyses on the asset. The analysis results are stored with the asset. This data can be used to assist in searching, or the data can be used to add extra functionality to your applications. Some of the analysis options are built-in and avaialable to all users, others are available to certain plans, and the rest are provided via Cloudinary add-ons.
  • Upload presets: Upload presets enable you to centrally define a set of asset upload options instead of specifying them in each upload call. You can define multiple upload presets, and apply different presets in different upload scenarios. Upload presets can be set as signed or unsigned.

See also:

  • Upload API Reference: Provides both REST and SDK syntax, parameter details, and examples for all methods of the Upload API.
  • Upload Add-ons: Many of Cloudinary's add-ons can be activated by adding a parameter in your upload call. These add-ons enable you to take advantage of special deep-learning, AI, and other analytical capabilities offered by Cloudinary as well as other vision and image processing partners.
  • Asset administration: Covers options for managing your uploaded assets programmatically, including various CRUD options, backups and version management, notifications and webhooks, and authentication and signature options.

✔️ Feedback sent!