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

# Managing upload presets for developers


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. 

You can set your presets as **signed** or **unsigned**. Unsigned presets can be used with unsigned upload calls, such as [uploading directly from the browser](client_side_uploading#direct_uploading_from_the_browser_via_a_backend_sdk), in the [upload widget](upload_widget) or for [Auto Upload](fetch_remote_images#auto_uploading_with_upload_presets) settings. 

## Use cases
Some use cases for using upload presets include:

* Define how the assets will be stored and accessed, such as the way the public ID value will be determined (`use_filename`), which folders they'll be stored in (`asset_folder`), and whether existing assets can be replaced by those uploaded with the preset (`overwrite`).
* Generate eager transformations for uploaded files (`eager`). This is especially valuable for video transformations that may take longer to generate and helps to ensure your uploaded files will be ready for delivery.
* Apply incoming transformations while uploading a file (`transformation`), for example to limit format types or file size before storing uploaded files in Cloudinary.
* Apply add-on capabilities, such as auto-tagging (`categorization`) or automatic moderation (`moderation`), to your uploads. 
* Update the behavior of [user-generated content](user_generated_content) uploads without modifying your website or mobile app code.
* Set up [default upload behavior](#default_upload_presets) for uploads via the Media Library or via [upload method](image_upload_api_reference#upload) commands.
* Use as upload preferences for uploads via the [Upload widget](upload_widget).

## Creating and managing upload presets
You can create, modify, or delete upload presets using the [Upload Preset](#managing_upload_presets_using_the_settings_ui) tab in the **Upload** page of the Console Settings or [programmatically](#managing_upload_presets_programmatically) using the `upload_presets` method of the Admin API. 

> **NOTES**:
>
> * When defining an upload preset that may be used for both image and video uploads, you can include both image-specific and video-specific upload options (e.g., for moderation or tagging add-ons) and only the relevant options will be used when a file is uploaded with that preset. Any upload options in your preset that apply to a different format are silently ignored. However, if you also supply [incoming or eager transformations](eager_and_incoming_transformations) as part of an upload call, make sure that all the transformation parameters included in the call are relevant for both images and videos.

> * Whether you create your upload preset via the Cloudinary Console or programmatically, upload presets may also impact the behavior of uploads that are performed in the Media Library. For more information, see [Managing upload presets in Assets](dam_admin_upload_presets).

> * The options available for upload presets, both in the UI and the API, are different if your product environment is using legacy **fixed folder mode**. For details about the UI, see [Folder modes - Upload preset options](dam_folder_modes#upload_preset_options), and for details about the API, see [Folder modes - Upload method](folder_modes#upload_method).* You can set up [lazy migration with auto-upload](migration#lazy_migration_with_auto_upload) using the [Auto Upload Mapping](https://console.cloudinary.com/app/settings/upload/mapping) tab in the **Upload** page of the Console settings to upload files only when first accessed. When adding a mapping, you need to specify  a **Target Folder** and an associated **Source URL Prefix**. If a requested asset isn't found within the specified **Target Folder**, it’s retrieved from the specified **Source URL prefix**. You can automatically apply a set of upload settings to assets uploaded via an upload mapping by associating the mapping with an upload preset. To do this, name the upload preset the same as the upload mapping’s **Target Folder**.

> * You can include the same parameters in upload presets as you can in direct uploads. For the full list of optional parameters, see the [upload](image_upload_api_reference#upload_optional_parameters) method in the Upload API.

> * The `callback` parameter is no longer supported for new upload presets. Existing upload presets that already include this parameter continue to work for backward compatibility.

### Managing upload presets using the settings UI

To create or modify an upload preset using the Upload Preset UI, navigate to the [Upload Presets](https://console.cloudinary.com/app/settings/upload/presets) page of the Console Settings.  
* To create a new upload preset, click **Add Upload Preset**.
* To modify an existing preset, select **Edit** from the preset's (3-dots) option menu. 
* To base a new upload preset on an existing one, select **Duplicate** from the (3-dots) option menu for the desired upload preset. The duplicate will appear at the top of the list with a random name. You can then select **Edit** to rename it and adjust the settings as needed.![Upload preset console UI](https://cloudinary-res.cloudinary.com/image/upload/bo_1px_solid_grey/f_auto/q_auto/v1731398012/docs/add_upload_preset_general.png "width:600, with_code:false, with_url:false, popup:true")
 
The upload preset page includes several sections where you can set a variety of upload options.

* The most important thing to consider when creating a new upload preset is whether you want the upload preset to be signed or unsigned. For example, only signed presets can be used as the [default upload preset](#default_upload_presets) for the Upload API or Media Library or if you are implementing [signed uploads](upload_images#authenticated_requests) for your application. Conversely, in most cases, you will need to use unsigned upload presets when implementing unsigned upload capabilities from your client-side app or when using the [upload widget](upload_widget) within a client-side app.

* In general, the options in the Upload Preset interface parallel the parameters you can set in an [upload method](image_upload_api_reference#upload) command. However, there are some options that may be available only [programmatically](#managing_upload_presets_programmatically). Those that are unavailable usually relate to specific sub-options of some of the add-ons or those related to complex transformation options, which might be relevant if you are defining [eager or incoming transformations](eager_and_incoming_transformations) for your upload preset.  

* The options relating to asset naming and folders differ depending on whether your product environment uses dynamic or fixed folder mode. For more information, see [Naming, storage and folder mode options](#naming_storage_and_folder_mode_options).

> **TIP**:
>
> You can configure a single **Notification URL** for an [upload preset](https://console.cloudinary.com/app/settings/upload/presets) in the **Advanced** tab to receive a notification each time an upload using this preset is completed. For more notification URL options, see [Webhook notifications](notifications).
When you finish and **Save** your upload preset definition, the upload preset and its settings are displayed in the **Upload Presets** page of the Console Settings: 

![Upload preset definition](https://cloudinary-res.cloudinary.com/image/upload/bo_1px_solid_grey/q_auto/f_auto/v1731398693/docs/upload_preset_definition_new.png "width:600, with_code:false, with_url:false")
### Managing upload presets programmatically

You can use the `upload_preset` method of the Admin API to create, manage, or delete upload presets, either via a REST API call, any of our backend SDKs. If you don't have a server-side application, you can manage upload presets programmatically using the [Cloudinary CLI](cloudinary_cli). For the most part, you can apply the same set of options for an upload preset as you can in an [Upload method](image_upload_api_reference#upload_optional_parameters) call. 

For example, the following code creates a new unsigned upload preset called `my_preset`, requests automatic-tagging using the Google tagging add-on engines for both images and videos, removes the backgrounds for images, and uploads to a folder called `new-products`:

```multi
|curl
curl \
  -d "name=my_preset&unsigned=true&categorization=google_tagging&categorization=google_video_tagging&auto_tagging=0.75&background_removal=cloudinary_ai&asset_folder=new-products" \
  -X POST \
  https://<API_KEY>:<API_SECRET>@api.cloudinary.com/v1_1/<cloud_name>/upload_presets

|ruby
Cloudinary::Api.create_upload_preset(
  name: "my_preset",
  unsigned: true, 
  categorization: "google_tagging,google_video_tagging",
  auto_tagging: 0.75,
  background_removal: "cloudinary_ai",  
  asset_folder: "new-products")

|php_2
$api->createUploadPreset([
    "name" => "my_preset", 
    "unsigned" => true, 
    "categorization" => "google_tagging,google_video_tagging",
    "auto_tagging" => 0.75,
    "background_removal" => "cloudinary_ai",  
    "asset_folder" => "new-products"]);  

|python
cloudinary.api.create_upload_preset(
  name = "my_preset",
  unsigned = True, 
  categorization = "google_tagging,google_video_tagging",
  auto_tagging = 0.75,
  background_removal = "cloudinary_ai",  
  asset_folder = "new-products")

|nodejs
cloudinary.v2.api
.create_upload_preset(
  { name: "my_preset", 
    unsigned: true, 
    categorization: "google_tagging,google_video_tagging",
    auto_tagging: 0.75,
    background_removal: "cloudinary_ai",  
    asset_folder: "new-products" })
  .then(result=>console.log(result));

|java
api.createUploadPreset(
  ObjectUtils.asMap(
    "name", "my_preset",
    "unsigned", true, 
    "categorization", "google_tagging,google_video_tagging",
    "auto_tagging", 0.75,
    "background_removal", "cloudinary_ai",  
    "asset_folder", "new-products"));

|csharp
var uploadPresetParams = new UploadPresetParams(){
  Name = "my_preset",
  Unsigned = true,
  Categorization = "google_tagging,google_video_tagging",
  AutoTagging = 0.75,
  BackgroundRemoval = "cloudinary_ai",  
  AssetFolder = "new-products"};
cloudinary.CreateUploadPreset(uploadPresetParams);

|go
resp, err := cld.Admin.CreateUploadPreset(ctx, admin.CreateUploadPresetParams{
	Name:     "my_preset",
	Unsigned: api.Bool(true),
	UploadParams: uploader.UploadParams{
		Categorization:    "google_tagging",
		AutoTagging:       0.75,
		BackgroundRemoval: "cloudinary_ai",
		AssetFolder:            "new-products"}})

|cli
cld admin create_upload_preset name="my_preset" unsigned="true" categorization="google_tagging,google_video_tagging" auto_tagging=0.75 background_removal="cloudinary_ai" asset_folder="new-products"
```

You can similarly use the Admin API to list, modify or delete existing upload presets. For complete details, see the [upload_preset](admin_api#upload_presets) method in the _Admin API Reference_.

### Naming, storage, and folder mode options

You may want to pay special attention to the following options that impact how your assets are named and stored. Some of these options differ between [dynamic and fixed folder mode](folder_modes).

Set them either from the [settings UI](#managing_upload_presets_using_the_settings_ui), or [programmatically](#managing_upload_presets_programmatically) using the [upload_presets](admin_api#upload_presets) endpoint of the Admin API. You can find the specific parameters that implement these options in the [Upload method](image_upload_api_reference#upload_optional_parameters) call. 

Option | Dynamic Folder Mode | Fixed Folder Mode
 --- | --- | ---
Public ID naming preferences | By default, the public ID is randomly generated to ensure uniqueness. However, to improve SEO, you can set the public ID to match the file name of the asset you're uploading (`use_filename:true`) with or without an added random suffix (`unique_filename:true/false`). | These options are the same for fixed folder mode.
Destination folder and URL path | You can specify an `asset_folder` value to define where the asset will be displayed within the Web interface. This has no impact on the asset's public ID path. If your organization has migrated from fixed folder mode to dynamic folder mode and wants to keep the old behavior for initial upload, or if your organization makes use of those paths in the delivery URL for SEO purposes, you can **Set the public ID path to match the *initial* asset folder path** (`use_asset_folder_as_public_id_prefix:true`), or you can separately specify a custom prefix to prepend the public ID (`public_id_prefix`). However, even when one of these options are set, if the asset is later moved to a different asset folder, the public ID path doesn't change.  | You can specify a destination `folder`, which automatically defines both the URL path to prepend to the public ID and the folder where the asset is stored. If the asset is later moved to a different folder, the URL path updates accordingly and could cause delivery URLs to break in production.
Display names | The upload preset provides options for setting naming preferences for display names, including using the uploaded asset's file name (`use_filename_as_display_name:true`) or matching the display name to the last segment of the public ID (`use_filename_as_display_name:false`). | There are no display names in fixed folder mode.

## Video tutorials

Watch the videos below to learn how to create upload presets in the Console and programmatically.

  
  
  
    Create Upload Presets in the Console
    Create and configure upload presets using the Console UI
  

  
  
  
    Create Upload Presets (Node.js)
    Streamline media uploads using signed upload presets 
  

## Upload preset precedence

When you use both an upload preset and pass request parameters directly in the same upload call, Cloudinary follows these precedence rules if you include the same parameter in both:

#### Signed uploads

For signed uploads, all **parameters provided directly in the upload request take precedence** over the same parameters defined in the upload preset, **except** `eager` and incoming `transformation` parameters, where Cloudinary merges the values (applies the values from both the preset and the request). 

#### Unsigned uploads

Unsigned uploads support a [limited set of parameters](image_upload_api_reference#unsigned_upload_parameters) passed directly in the request. 

When you include one of the supported parameters in both the unsigned upload preset and in the unsigned upload request, **the parameter in the preset takes precedence, except**:

* **Merged parameters** (applies values from both preset and request): `context`, `metadata`
* **Request takes precedence**: `filename_override`, `public_id` (unless `disallow_public_id` is `true` in the preset)

## Best practices for upload presets

When configuring upload presets consider these best practices to optimize performance and avoid common issues:

### Eager and incoming transformations

#### Avoid using the same transformation in both incoming and eager transformations

Choose one approach based on your use case. Using the same transformation in both incoming and eager can lead to unexpected results or redundant processing.

#### Don't use f_auto - use specific formats instead

The `f_auto` parameter works by detecting the requesting browser at delivery time to serve the optimal format. Since there is no requesting browser during upload, `f_auto` is meaningless in both eager and incoming transformation contexts.

**For eager transformations**, explicitly specify the exact format(s) you need to pre-generate. This applies to both images and videos. When configuring video eager transformations, eagerly generate the specific format and codec combinations you need for delivery to ensure all required variants are ready immediately. 

For example, to create an upload preset with video eager transformations, specify the following:

* `f_webm` with `vc_vp9` (VP9 codec in WebM format)
* `f_mp4` with `vc_av1` (AV1 codec in MP4 format) 
  > **NOTE**: `avi` is a premium feature for Enterprise customers, [contact support](https://support.cloudinary.com/hc/en-us/requests/new) to check availability.
* `f_mp4` with `vc_h265` (H.265/HEVC codec in MP4 format) 
* `f_mp4` with `vc_h264` (H.264/AVC codec in MP4 format)

```multi
|ruby
Cloudinary::Api.create_upload_preset(
  name: "video_preset",
  unsigned: false,
  eager: [
    {fetch_format: "webm", video_codec: "vp9", format: ""},
    {fetch_format: "mp4", video_codec: "av1", format: ""},
    {fetch_format: "mp4", video_codec: "h265", format: ""},
    {fetch_format: "mp4", video_codec: "h264", format: ""}])

|php_2
$api->createUploadPreset([
  "name" => "video_preset",
  "unsigned" => false,
  "eager" => [
    ["fetch_format" => "webm", "video_codec" => "vp9", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "av1", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h265", "format" => ""],
    ["fetch_format" => "mp4", "video_codec" => "h264", "format" => ""]]]);

|python
cloudinary.api.create_upload_preset(
  name = "video_preset",
  unsigned = False,
  eager = [
    {"fetch_format": "webm", "video_codec": "vp9", "format": ""},
    {"fetch_format": "mp4", "video_codec": "av1", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h265", "format": ""},
    {"fetch_format": "mp4", "video_codec": "h264", "format": ""}])

|nodejs
cloudinary.v2.api.create_upload_preset({
  name: "video_preset",
  unsigned: false,
  eager: [
    {fetch_format: "webm", video_codec: "vp9", format: ""},
    {fetch_format: "mp4", video_codec: "av1", format: ""},
    {fetch_format: "mp4", video_codec: "h265", format: ""},
    {fetch_format: "mp4", video_codec: "h264", format: ""}]})
  .then(result => console.log(result));

|java
api.createUploadPreset(
  ObjectUtils.asMap(
    "name", "video_preset",
    "unsigned", false,
    "eager", Arrays.asList(
      new EagerTransformation().fetchFormat("webm").videoCodec("vp9").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("av1").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h265").format(""),
      new EagerTransformation().fetchFormat("mp4").videoCodec("h264").format(""))));

|csharp
var uploadPresetParams = new UploadPresetParams(){
  Name = "video_preset",
  Unsigned = false,
  Eager = new List<Transformation>(){
    new EagerTransformation().FetchFormat("webm").VideoCodec("vp9").Format(""),
    new EagerTransformation().FetchFormat("mp4").VideoCodec("av1").Format(""),
    new EagerTransformation().FetchFormat("mp4").VideoCodec("h265").Format(""),
    new EagerTransformation().FetchFormat("mp4").VideoCodec("h264").Format("")}};
cloudinary.CreateUploadPreset(uploadPresetParams);

|cli
cld admin create_upload_preset name="video_preset" unsigned=false eager='[{"fetch_format":"webm","video_codec":"vp9","format":""},{"fetch_format":"mp4","video_codec":"av1","format":""},{"fetch_format":"mp4","video_codec":"h265","format":""},{"fetch_format":"mp4","video_codec":"h264","format":""}]'
```

**For incoming transformations**, specify a concrete target format if format conversion is needed, such as `f_jpg` to convert all uploaded images to JPEG, or `f_mp4` with a specific video codec to normalize video formats before storage.

For example, to normalize user-uploaded images to JPEG format:

```multi
|ruby
Cloudinary::Api.create_upload_preset(
  name: "normalize_images",
  transformation: {fetch_format: "jpg", quality: "auto"})

|python
cloudinary.api.create_upload_preset(
  name = "normalize_images",
  transformation = {"fetch_format": "jpg", "quality": "auto"})

|nodejs
cloudinary.v2.api.create_upload_preset({
  name: "normalize_images",
  transformation: {fetch_format: "jpg", quality: "auto"}})
  .then(result => console.log(result));

|cli
cld admin create_upload_preset name="normalize_images" transformation='{"fetch_format":"jpg","quality":"auto"}'
```

> **TIP**: For more information on pre-generating formats using eager transformations, including additional SDK examples and responses, see [Using automatic format in eager transformations](eager_and_incoming_transformations#using_automatic_format_in_eager_transformations).

#### Use asynchronous processing for time-intensive transformations

Video transformations and other time-intensive processes, such as moderating large files, can benefit from asynchronous processing. When configuring presets for videos or large files, set `eager_async` to `true` and provide an `eager_notification_url` to process transformations in the background and receive a notification when complete. See [Eager asynchronous transformations](eager_and_incoming_transformations#eager_asynchronous_transformations).

**Example:**

```multi
|ruby
Cloudinary::Api.create_upload_preset(
  name: "async_video_preset",
  eager: [{width: 500, height: 500, crop: "fill"}],
  eager_async: true,
  eager_notification_url: "https://mysite.example.com/eager_endpoint")

|php_2
$api->createUploadPreset([
  "name" => "async_video_preset",
  "eager" => [["width" => 500, "height" => 500, "crop" => "fill"]],
  "eager_async" => true,
  "eager_notification_url" => "https://mysite.example.com/eager_endpoint"]);

|python
cloudinary.api.create_upload_preset(
  name = "async_video_preset",
  eager = [{"width": 500, "height": 500, "crop": "fill"}],
  eager_async = True,
  eager_notification_url = "https://mysite.example.com/eager_endpoint")

|nodejs
cloudinary.v2.api.create_upload_preset({
  name: "async_video_preset",
  eager: [{width: 500, height: 500, crop: "fill"}],
  eager_async: true,
  eager_notification_url: "https://mysite.example.com/eager_endpoint"})
  .then(result => console.log(result));

|cli
cld admin create_upload_preset name="async_video_preset" eager='[{"width":500,"height":500,"crop":"fill"}]' eager_async=true eager_notification_url="https://mysite.example.com/eager_endpoint"
```

### Signed and unsigned upload preset security

#### Choose signed vs unsigned based on use case

Upload presets can be configured as either signed or unsigned:

* **Signed presets**: Use for authenticated uploads from your backend. They support all upload parameters and require generating an [authentication signature](authentication_signatures) in the upload request.

* **Unsigned presets**: Use for unauthenticated uploads from client-side applications (browser/mobile) without requiring signature generation. However, they have restrictions:
  * Upload requests using unsigned presets can only pass a [limited set of parameters](image_upload_api_reference#unsigned_upload_parameters) directly in the request
  * All other configuration must be predefined in the preset itself
  * The preset name will be visible in client-side code

For more information on authenticated vs unauthenticated uploads, see [Authenticated requests](upload_images#authenticated_requests) and [Unauthenticated requests](upload_images#unauthenticated_requests).

#### Protect unsigned presets

Unsigned preset names can be discovered in client-side code. Apply protective measures in your unsigned presets such as:

* Restrict allowed file formats with `allowed_formats`.
* Limit file size with the `max_file_size` parameter.
* Set `disallow_public_id` to prevent users from specifying public IDs.
* Apply [incoming transformations](eager_and_incoming_transformations#incoming_transformations) to normalize asset dimensions/duration before storage.

For example, here's an unsigned preset with security measures:

```multi
|ruby
Cloudinary::Api.create_upload_preset(
  name: "secure_unsigned_preset",
  unsigned: true,
  allowed_formats: "jpg,png,mp4",
  max_file_size: 10485760,  # 10MB in bytes
  disallow_public_id: true)

|php_2
$api->createUploadPreset([
  "name" => "secure_unsigned_preset",
  "unsigned" => true,
  "allowed_formats" => "jpg,png,mp4",
  "max_file_size" => 10485760,  # 10MB in bytes
  "disallow_public_id" => true]);

|python
cloudinary.api.create_upload_preset(
  name = "secure_unsigned_preset",
  unsigned = True,
  allowed_formats = "jpg,png,mp4",
  max_file_size = 10485760,  # 10MB in bytes
  disallow_public_id = True)

|nodejs
cloudinary.v2.api.create_upload_preset({
  name: "secure_unsigned_preset",
  unsigned: true,
  allowed_formats: "jpg,png,mp4",
  max_file_size: 10485760,  // 10MB in bytes
  disallow_public_id: true})
  .then(result => console.log(result));

|cli
cld admin create_upload_preset name="secure_unsigned_preset" unsigned=true allowed_formats="jpg,png,mp4" max_file_size=10485760 disallow_public_id=true
```

### Optimization and performance

#### Balance storage vs delivery performance

* Use **incoming transformations** to reduce storage costs by normalizing [user-generated content](user_generated_content) (e.g., limit resolution, strip metadata).
* Use **eager transformations** to pre-generate frequently accessed derivatives and improve first-time delivery performance.
* Avoid generating unnecessary eager transformations that increase storage without meaningful benefit.

#### Test before production

Always test new upload presets with sample assets before deploying to production, especially when using eager or incoming transformations. Verify that:

* Eager transformations generate the expected formats and quality.
* Incoming transformations don't over-compress or degrade asset quality.
* Delivery URLs use the exact same parameter order as the eager transformations (e.g., if you eagerly generate `c_fill,h_400,w_600`, your delivery URL must use that exact order, not `c_fill,w_600,h_400`).

### Naming and organization

#### Use descriptive preset names

Choose clear names that indicate purpose and settings (e.g., `video-social-hls`, `user-profile-photos`, `product-images-ecommerce`).

#### Document your presets

Maintain documentation for your team about what each preset does and when to use it, especially if you have multiple presets for similar use cases.

## Default upload presets

From the [Upload](https://console.cloudinary.com/app/settings/upload) page of the Console Settings, you can also individually select **signed** upload presets that will act as the default upload presets for images, videos, and raw files respectively. You can select one set of presets for API calls and another set of default presets for uploads via the **Media Library**. 

The settings in these default presets are applied to all uploads of the relevant asset type whenever no other upload preset is specified directly in an upload call, in your [Upload widget](upload_widget) code, or via the Advanced options of the upload widget in the Media Library.
![Default upload preset settings](https://cloudinary-res.cloudinary.com/image/upload/q_auto/f_auto/bo_1px_solid_grey/v1733820596/docs/DAM/upload_preset_defaults.png "thumb: w_600,dpr_2, width:600, with_code:false, with_url:false, popup:true")
Make sure you coordinate with everyone in your organization who uses or manages this product environment before making any changes to which upload presets are selected as defaults or before changing the settings in any upload preset set as a default, since any change could break production code or processes.

> **TIP**:
>
> The default Media Library presets apply to any assets that are dragged to a folder using the **Media Library** UI in your Console. They are also used by default when you select files from any source via the built-in Upload Widget in the Media Library. 
> However, if enabled for your account, then you can optionally select a different signed upload preset to use just for that upload in the **Advanced** options of the Media Library Upload Widget. For details, see [Media Library Upload Widget](dam_upload_store_assets#media_library_upload_widget).

