Uploading assets

Last updated: Mar-26-2023

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.

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, e-commerce stores and more. For details, see Uploading and storing assets in the Digital Asset Management guide and the Platform integration guides.

Related topics

Programmatic upload video tutorial

Watch this demo on how to quickly upload images, videos and other media files to Cloudinary for immediate deliverability using Cloudinary's Upload API in your development environment.

Uploading assets to the cloud

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

  • Usage limits for uploading, transforming and delivering files depend on your Cloudinary plan. For details, check the Account tab in your Cloudinary Console Settings.
  • For additional information on how your overall account usage is calculated (including storage and bandwidth), see the Cloudinary Pricing page and this KB article.
  • You can set your email preferences to receive notifications regarding your account usage.

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 backend 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:

For a full listing of the possible optional parameters (options = {}) available for the upload method, see the Upload API reference.

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

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

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 looks something like this: 8jsb1xofxdqamu2rzwt9q. The resulting delivery URL for such an asset would be something like:


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:

  • The public ID value for image and video asset types should not include the file extension. If you include a . character in a public ID, it's simply another character in the public ID value 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.

  • Public IDs can be up to 255 characters, including non-English characters, periods (.), forward slashes (/), underscores (_), hyphens (-).
  • Public ID values cannot begin or end with a space or forward slash (/). Additionally, they cannot include the following characters: ? & # \ % < > +

Including a path in the Public ID

The Public ID value can include path elements (slashes) for more structured delivery URLs and to assist with SEO. For example:

This can also be done by splitting the Public ID into 2 parts, specifying only the last element of the public ID in the public_id parameter, and specifying the public ID path in the folder parameter. Using the same example as above, but this time with the folder parameter:

  • You cannot use 'v' followed by numeric characters as the name of a path element in your public ID.
  • It's recommended to avoid using public ID path names starting with 1-3 characters followed by an underscore, such as my_path. By default, Cloudinary assumes that URL components following that pattern represent a Cloudinary transformation component. If the first path element of a public_id does follow that pattern, then when delivering assets from that path, you must separate the last transformation component from the path element with a version component. For example:

  • For details on delivering Public IDs in a path structure with or without versions, see Asset versions.
  • The effect on the Media Library of including path elements in public IDs depends on whether your product environment is using fixed folder mode or dynamic folder mode.
    • If your product environment is using fixed folder mode (most accounts and product environments created before September 2022 are using this mode), then including slashes in a public ID will also create folders in the same structure in the Media Library. If an asset is moved to a different folder in the Media Library, that results in a change to the asset's public ID.
    • If Dynamic folders mode is enabled on your product environment, slashes in a public ID do not impact how the asset is organized in the Media Library. Additionally, if in this mode, you should use the new asset_folder parameter instead of the folder parameter mentioned above to set the Media Library folder. Whether or not you define an asset folder for purposes of organizing assets in the Media Library, if you also want your public_id to include slashes, make sure to use one of the options available in that mode to set the public ID path.
    • If your product environment is using dynamic folder mode, you'll see a Dynamic Folders indication at the top of the Media Library Preferences in the console, and the response of a Get details of a resource method will include display_name and asset_folder response keys.
    • For more details on dynamic folders mode, see Dynamic folders - New Upload API parameters.

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:

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.

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 from a local path, a remote URL, a private storage URL (S3 or Google Cloud storage), a base64 data URI, or an FTP URL.

Upload from a 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:

Upload from a remote 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 Cloudinary. This option allows for a much faster migration of your existing media files. For example:

Upload from a private storage URL (Amazon S3 or Google Cloud)

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

  • 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 product environment with the specified cloud name.
    • If you want this bucket to be whitelisted for more than one Cloudinary product environment, 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.

S3 example:

Google Cloud example:

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:

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.

Upload via a base64 data URI

You can upload a file by specifying the Data URI of the file in base64 encoding (no larger than 100 MB). For example:

Upload from an 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 FTP URL syntax taking the form: ftp://<user>:<password>@<host>:<port>/<url-path>. For example:

Asset types

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

Uploading a password-protected PDF as an image asset is not supported. If necessary, you can upload a password-protected PDF by setting the resource_type to raw in the upload command. However, keep in mind that like any other raw file, you can deliver a raw PDF as is, but PDF transformations are not supported for raw assets.

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:

The auto value is especially useful when you don't know what type of files your users will 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 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 backend 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 100 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, 300 MB for paid plans). Therefore, it's best practice to generate your video transformations eagerly on upload.

Here's a simple video upload example:

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:

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.

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.

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

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.

    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

An existing image or video asset will be replaced by a newly uploaded file when overwrite is set to true and:

  • You upload a new media asset while specifying its public_id to be the same as an existing asset
  • The asset gets the same public ID as an existing one via the use_filename=true upload option
  • You use an upload preset where one of the above options is applied

If backups are enabled for your product environment, then when an asset is replaced, the previous version is backed up and can be restored if needed.

However, if the original (older) asset has already been generated and accessed, it might already be cached on the CDN. If an end-user accesses the identical 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 Cloudinary delivery URLs that can be added 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.

  • Delivering the URL without a version value will deliver the cached version on the CDN if available or will request the latest version from Cloudinary if not cached (or when the cached version expires).
  • Delivering the URL with a version will deliver the cached CDN version only if the cached version matches the requested version number. Otherwise, it will bypass the cached CDN version and immediately request and deliver the latest version from Cloudinary.

Example image delivery URL without version:


Example image delivery URL with version:


As an alternative to using versions to ensure that a new version of an asset is delivered, you can set the invalidate parameter to true while uploading a new version of an asset in order to invalidate the previous media asset throughout the CDN. Note that 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.

  • Depending on your product environment setup, overwriting an asset may clear the tags, contextual, and structured metadata values for that asset. If you have a Master admin role, you can change this behavior for your product environment in the Media Library Preferences pane, so that these field values are retained when new version assets overwrite older ones (unless you specify different values for the tags, context, or metadata parameters as part of your upload).
  • You cannot use 'v' followed by numeric characters as the name of a public ID path component.
  • There are a number of important considerations when using the invalidate functionality. For example, if there is no version number in a URL that includes a public ID with slashes, then by default, those URLs are not invalidated. For details on invalidating media assets, see Invalidating cached media assets on the CDN.

See also: Backups and version management

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.

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. See Code explorer: Chunked asset upload from the client side.

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:

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:

Code explorer: Chunked asset upload from the client side

Here's an example of uploading large files using pure client-side code, in this case React.

Run the app

To try this out you'll need an unsigned upload preset configured for your product environment.

Set your cloud name and the name of the upload preset in CldCustUploadLgRestApi.js.

This code is also available in GitHub.

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:

The URLs returned in the response include a version number. Including the version in the delivery URL is optional.

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 an SHA (Secure Hash Algorithm) cryptographic function on the following parameters: public_id, version and api_secret.

By default, Cloudinary supports both SHA-1 and SHA-256 digests for validation, and you can use either. The SDK methods use the SHA-1 algorithm by default, but you can use the SHA-256 algorithm instead by setting the signature_algorithm SDK configuration parameter to sha256. If you want to limit your account to allow only the SHA-256 digest for all your validations, submit a request.

Use the Cloudinary SDK's verify_api_response_signature method to verify the signature in the response.

Alternatively, you can use the Cloudinary SDK's api_sign_request method to generate a signature on your back-end for comparison purposes.

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

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 an SHA cryptographic 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:

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:

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


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:

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


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:

Direct uploading from the browser

This section gives details on how to use one of Cloudinary's Backend SDKs to upload a file directly to Cloudinary and bypass your own servers. For uploading directly with a Cloudinary Frontend SDK, see Direct uploading from the browser in the jQuery SDK. However, if you are only using Frontend code, then an easier solution may be to implement Cloudinary's Upload Widget in your code.

The upload samples shown in the sections 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):

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.

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 product environment 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 product environment with the unsigned_1 upload preset:

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:

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.

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:

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:

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:

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

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. First, include the remote JavaScript file of the upload widget:

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

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


  • cloud name is the name of your Cloudinary product environment.
  • 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' product environment, send an HTTPS POST request to the following URL:


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 product environment.
  • 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 product environment. 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.

Optional parameters:

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

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.

Code explorer: Upload multiple files using a form (unsigned)

This example shows one way to upload selected local files to Cloudinary using a direct call to the REST API. The call is made via an unauthenticated POST request as this is purely client-side code, so an unsigned upload preset (docs_upload_example_us_preset) is used.

This code is also available in GitHub.

See also: Code explorer: Chunked asset upload from the client side

Code explorer: Upload multiple files using a form (signed)

To perform an authenticated request, you need to call a server-side component to generate a signature using your API secret, which should never be exposed on the client side. Having obtained the signature and timestamp from your server, you can use similar code to the above unauthenticated example, just appending your API key, timestamp and signature to formData. See signed-uploads/public/js/uploadclientform.js in the following example.

Run the app
  1. Click Remix to Edit
  2. Enter your Cloudinary credentials in signed-uploads/public/js/config.js
  3. Click View App
  4. Click the Upload Files Using a Form link

This code is also available in GitHub.

Generating authentication signatures

When using the Cloudinary SDKs for any upload or admin method that requires a signature, the signature is automatically generated and added to the request. If, however, you are making direct calls to the REST API, you need to generate a signature yourself. You can do this manually, or by using a Cloudinary backend SDK signature generation method.

Manual signature generation

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.

By default, Cloudinary supports both SHA-1 and SHA-256 digests for validation, and you can use either. The SDK methods use the SHA-1 algorithm by default, but you can use the SHA-256 algorithm instead by setting the signature_algorithm SDK configuration parameter to sha256. If you want to limit your account to allow only the SHA-256 digest for all your validations, 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 an SHA cryptographic function.

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 product environment:

The body of the POST request must be stringified, as seen in the example above (all parameters are included as a single string, even when the content type is JSON).

Or, using the POST request from the form example with a selected local file:

See also
Have a look at 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 backend SDKs to generate SHA authentication signatures

You can use one of Cloudinary's backend SDKs to generate the authentication signature. The api_sign_request method uses the SHA-1 algorithm by default, but you can use the SHA-256 algorithm instead by setting the signature_algorithm SDK configuration parameter to sha256. Make sure that the timestamp is included in the params_to_sign object.

The following Node.js app contains two examples of using the api_sign_request method to provide a signature for uploading files:

  • signed-uploads/modules/signuploadwidget.js provides a signature for uploading files using the upload widget (corresponding to signed-uploads/public/js/uploadclientwidget.js)
  • signed-uploads/modules/signuploadform.js provides a signature for uploading files using a form (corresponding to signed-uploads/public/js/uploadclientform.js)

Run the app
  1. Click Remix to Edit
  2. Enter your Cloudinary product environment credentials in signed-uploads/public/js/config.js
  3. Click View App
  4. Try both upload options

This code is also available in GitHub.

See also
Watch this video tutorial explaining how to generate a signature using the Node.js SDK for use in a direct call to the REST API.

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.

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:

Uploading 3D models

Cloudinary supports 3D models in various formats. Where the format requires or references other files (for example, textures or other images used in the model), you should zip the entire folder and upload the single ZIP file to Cloudinary.

In order to use 3D models in the Product Gallery and perform transformations on them, the 3D model needs to be uploaded as an image asset type to Cloudinary.

ZIP files are normally uploaded as raw files if the asset type is not specified. However, Cloudinary is able to detect some 3D models and upload them as image types, which is especially useful if uploading manually from within your Media Library.

If you are uploading a 3D model programmatically, you can explicitly set resource_type to image. For example, to upload the 3D model archived in the sample_3D.zip file:

Retrieving and delivering remote files on the fly

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

Fetch enables on-the-fly transformation and optimized delivery of existing remote images and videos via CDN. Fetched assets are cached on your Cloudinary product environment for performance reasons. Paid customers can request to enable a refresh option for checking the remote asset on a regular basis, and if the remote asset changes, the cached asset is updated accordingly.

For example, to fetch a remote image of Benedict Cumberbatch fetched by Cloudinary from WikiMedia:

Remote asset retrieved and delivered using fetch

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

For example, if you create a folder called remote_media 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:


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

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 Cloudinary just like any other uploaded asset with a Public ID of remote_media/commons/7/75/Benedict_Cumberbatch_2011.jpg.

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 Cloudinary, 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!

Rate this page: