> ## Documentation Index
> This page is part of the Image and Video APIs product. Fetch the complete documentation index for Image and Video APIs at: https://cloudinary.com/documentation/llms-image-and-video-apis.txt?referrer=docpage and then use it to discover all relevant pages before exploring further.
> If your task extends beyond this product, fetch the top-level index covering all Cloudinary products and topics at: https://cloudinary.com/documentation/llms.txt?referrer=docpage

# Upload UGC


Upload is an essential feature of UGC: you have to provide your users a way to add their media to your site or app. In addition to storing the media in your product environment, there are many features that you can invoke while uploading, for example, [limiting the size](#transform_on_upload) of the uploads, [moderating the content](user_generated_content_manage_analyze#moderate_automatically) that's uploaded, and [analyzing the media](user_generated_content_manage_analyze#analyze_quality_and_accessibility) for management purposes.

This page focuses on how upload applies to the four [example use cases](user_generated_content#popular_applications_of_ugc) followed throughout this guide: profile pictures, video reviews, marketplace products, and try before you buy.

> **NOTE**: Moderation and analysis are discussed under [Manage and analyze](user_generated_content_manage_analyze), although they can (and should) be invoked as part of the upload flow.

## Recommended features by use case

The following table shows which features we recommend (marked ✅) for each of these use cases:

{table:class=no-borders overview textcenter}  | Profile pictures | Video reviews | Marketplace products | Try before you buy
---|---|---|---|---
[Upload](#ways_to_upload) | ✅  | ✅  | ✅  | ✅ 
[Define upload behavior](#define_upload_behavior) | ✅  | ✅  | ✅  | ✅ 
[Control access to uploaded media](#control_access_to_uploaded_media) | | ✅ | ✅ 
[Track uploads](#track_uploads) | |  ✅  | ✅ |
[Transform on upload](#transform_on_upload) | ✅  | ✅  | ✅  | ✅ 
[Prepare delivery transformations](#prepare_delivery_transformations_on_upload_cache_warm_up) | | ✅  | ✅ |

## Ways to upload

### API and SDKs

There are many ways to allow users to upload their content to your site. Using the [Upload API](image_upload_api_reference), either directly, or via an [SDK](cloudinary_sdks), you can tailor how images and videos are uploaded, analyzed and managed to suit your needs.

The following code shows how to:

* Upload a local image called **shirt.jpg**
* Request [color and quality analysis](semantic_data_extraction)
* Run the [Google Auto Tagging](google_auto_tagging_addon#adding_resource_tags_to_images) add-on 
* Automatically add the detected categories as tags to the asset

```multi
|ruby 
Cloudinary::Uploader.upload("shirt.jpg",  
  quality_analysis: true,
  colors: true,
  categorization: "google_tagging",
  auto_tagging: 0.7)

|php_2
use Cloudinary\Api\Upload\UploadApi;

(new UploadApi())->upload('shirt.jpg', [
  'quality_analysis' => true,  
  'colors' => true, 
  'categorization' => 'google_tagging', 
  'auto_tagging' => 0.7]);
    
  
|python
cloudinary.uploader.upload("shirt.jpg", 
  quality_analysis = True, 
  colors = True,  
  categorization = "google_tagging",
  auto_tagging = 0.7)

|nodejs
cloudinary.v2.uploader
.upload("shirt.jpg", { 
  quality_analysis: true, 
  colors: true, 
  categorization: "google_tagging",
  auto_tagging: 0.7})
.then(result=>console.log(result));
  
|java
Map params = ObjectUtils.asMap(
    "quality_analysis", true,
    "colors", true,
    "categorization", "google_tagging", 
    "auto_tagging", 0.7);
Map uploadResult = cloudinary.uploader().upload(new File("shirt.jpg"), params);

|csharp
var uploadParams = new ImageUploadParams()
    {
        File = new FileDescription(@"shirt.jpg"), 
        QualityAnalysis = true,
        Colors = true,        
        Categorization = "google_tagging",
        AutoTagging = 0.7};
var uploadResult = cloudinary.Upload(uploadParams);

|android
MediaManager.get().upload("shirt.jpg")
   .unsigned("preset1")
   .option("quality_analysis", "true")
   .option("colors", "true")
   .option("categorization", "google_tagging")
   .option("auto_tagging", "0.7")
   .dispatch();

|swift
let params = CLDUploadRequestParams().setQualityAnalysis(true).setColors(true).setCategorization("google_tagging").setAutoTagging(0.7)
let request = cloudinary.createUploader().upload(data: fileUrl, uploadPreset: "preset1", params: params)

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=https://www.example.com/shirt.jpg&quality_analysis=true&colors=true&categorization="google_tagging"&auto_tagging=0.7&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

### Upload widget

For a complete, interactive user interface that enables users to upload files from a variety of sources, and includes options to crop on upload and limit file types, amongst others, consider implementing the Cloudinary [Upload widget](upload_widget). 

This example of the Upload widget restricts file types to images only and displays the uploaded image following a successful upload:

Try the Upload widget

  
                

Some of the [community-developed libraries](community_sdks) have a `CldUploadWidget` component for adding the widget to your app.

Watch a clip about the Upload widget from the [Cloudinary Academy UGC workshop](https://training.cloudinary.com/courses/using-cloudinarys-incoming-transformations-for-perfectly-crafted-user-generated-content-45-minute-workshop):

  This video is brought to you by Cloudinary's video player - embed your own!Use the controls to set the playback speed, navigate to chapters of interest and select subtitles in your preferred language.
{videoTranscript:publicId=training/5-upload-widget}

> **TIP**: Head to the [Cloudinary Academy](https://training.cloudinary.com) to take the full workshop or browse others - free for all Cloudinary users!
### Minisite

Non-developers can create a hosted, standalone site for the Upload widget by creating a minisite. See this [no-code uploads blog post](https://cloudinary.com/blog/no-code-uploads-to-cloudinary) to learn more.

### Portals

If you're on an [Enterprise plan](https://cloudinary.com/pricing#pricing-enterprise), you can use the **external uploader** feature of [Portals](dam_admin_portals) to allow third-party stakeholders to upload assets directly to your product environment using the Upload Widget, embedded within the portal. 

You can configure the external uploader to:

* Automatically apply auto-tagging
* Assign an identifying tag to all assets uploaded via the portal

### Media Library 

For trusted content providers, there's also the option to provide them with their own [Media Library user](dam_admin_users_groups#role_based_permissions) login to your product environment, where they can not only upload, but also search, view and download assets within the folders that they have permission to see.

## Define upload behavior

You can use [upload presets](upload_presets) to define a set of upload options that are applied every time a user uploads content to your site. For example, you can specify that all assets are [moderated](user_generated_content_manage_analyze#moderate) on upload, or that certain [transformations are applied](#transform_on_upload).

Watch a clip about upload presets from the [Cloudinary Academy UGC workshop](https://training.cloudinary.com/courses/using-cloudinarys-incoming-transformations-for-perfectly-crafted-user-generated-content-45-minute-workshop):

  This video is brought to you by Cloudinary's video player - embed your own!Use the controls to set the playback speed, navigate to chapters of interest and select subtitles in your preferred language.
{videoTranscript:publicId=training/4-upload-presets}

> **TIP**: Head to the [Cloudinary Academy](https://training.cloudinary.com) to take the full workshop or browse others - free for all Cloudinary users!
## Control access to uploaded media

By default, files uploaded to your product environment are publicly available via a URL. If you want to control who can access your assets and whether or not they can transform them, you should consider the different [media access methods](control_access_to_media).

## Track uploads

You can get notified when content is uploaded to your site via [webhook notifications](notifications). Use these notifications to trigger further steps in your workflow automatically, or prompt subsequent interaction.

## Transform on upload

You can apply transformations to images and videos as they're uploaded. These are called [incoming transformations](eager_and_incoming_transformations#incoming_transformations) and result in the transformed assets being stored, rather than the original assets. Incoming transformations are useful to limit the size of uploaded assets, and allow you to standardize a set of transformations for your use case. 

> **TIP**: You can also [transform](user_generated_content_transform_customize) images and videos on delivery (leaving the original intact), which allow users to make customizations on the fly, apply different transformations to the same assets, and make optimizations based on the user's device.

Watch a clip about incoming transformations from the [Cloudinary Academy UGC workshop](https://training.cloudinary.com/courses/using-cloudinarys-incoming-transformations-for-perfectly-crafted-user-generated-content-45-minute-workshop):

  This video is brought to you by Cloudinary's video player - embed your own!Use the controls to set the playback speed, navigate to chapters of interest and select subtitles in your preferred language.
{videoTranscript:publicId=training/3-incoming-transformations}

> **TIP**: Head to the [Cloudinary Academy](https://training.cloudinary.com) to take the full workshop or browse others - free for all Cloudinary users!
### Limit dimensions of images and videos

If you know that when displaying your users' images or videos they'll never exceed certain dimensions, then you can resize the media to a defined [limit](image_resize_modes#limit) on upload to save storage costs. 

### Truncate long videos

To prevent users from uploading overly long videos, you can set a limit and [truncate](video_trimming#trimming_videos) anything longer than that limit.

### Strip metadata

For privacy reasons, and also to reduce storage costs, it's advisable to [remove metadata](transformation_reference#fl_force_strip) (IPTC, EXIF and XMP) associated with images on upload.

## Prepare delivery transformations on upload (cache warm up)

It can sometimes take more than a couple of a seconds to transform an image or video on the fly for delivery, for example, when transforming long videos or using generative AI transformations. You can prepare derived (transformed) versions of an asset in advance of delivering them for the first time by using [eager transformations](eager_and_incoming_transformations#eager_transformations) to warm up the cache.

You can specify eager transformations in an [upload preset](#define_upload_behavior), or use the `eager` parameter in the `upload` call:

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

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

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

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

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

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

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

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

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

> **READING**:
>
> * [User-generated content](user_generated_content): Overview and the UGC workflow diagram.

> * [Manage and analyze UGC](user_generated_content_manage_analyze): Moderate, scan for malware, analyze, transcribe, and automate workflows.

> * [Transform and customize UGC](user_generated_content_transform_customize): Improve quality, resize, standardize, watermark, and personalize.

> * [Optimize and deliver UGC](user_generated_content_optimize_deliver): Optimize on the fly and deliver videos with the Cloudinary Video Player.
