> ## 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.

# Moderate assets


It's sometimes important to moderate assets uploaded to Cloudinary: you might want to keep out inappropriate or offensive content, reject assets that do not answer your website's needs (e.g., making sure there are visible faces in profile images), or make sure that photos are of high enough quality before making them available on your website. Moderation can be especially valuable for [user-generated content](user_generated_content). Whether using the server-side upload API call, when allowing users to upload the assets directly from their browser, or on updating an existing asset, you can mark an asset for moderation by adding the `moderation` parameter to the call. The parameter can be set to:

* `perception_point` for automatic moderation with the [Perception Point Malware Detection add-on](perception_point_malware_detection_addon)
* `webpurify` for automatic **image** moderation with the [WebPurify's Image Moderation add-on](webpurify_image_moderation_addon)
* `aws_rek` for automatic **image** moderation with the [Amazon Rekognition AI Moderation add-on](aws_rekognition_ai_moderation_addon) 
* `aws_rek_video` for automatic **video** moderation with the [Amazon Rekognition Video Moderation add-on](aws_rekognition_video_moderation_addon)
* `google_video_moderation` for automatic **video** moderation with the [Google AI Video Moderation add-on](google_ai_video_moderation_addon) 
* `duplicate:<threshold>` for automatic duplicate **image** detection with the [Cloudinary Duplicate Image Detection add-on](cloudinary_duplicate_image_detection_addon) 
* `manual` for [manually moderating](#moderating_assets_via_the_media_library) any asset via the Media Library

> **TIP**:
>
> :title=Tips

> * Take a look at the [profile picture](profile_picture_sample_project) and [video review](video_review_sample_project) sample projects, which demonstrate UGC use-cases where images and videos are moderated on upload using Amazon Rekognition and Perception Point.

> * You can view assets sent for automatic or manual moderation in the **Moderation** tab of the Media Library to verify that your programmatic action was applied successfully. Filter by the relevant moderation type and status to find the assets you need. For more information, see [Moderating assets](media_library_for_developers) on the _Media Library for developers_ page.

> **INFO**: You're responsible for ensuring that all content stored in Cloudinary complies with our [Terms of Use](https://cloudinary.com/tou), and the moderation features on this page can help with that. For details about Cloudinary's content monitoring and what happens if policy violations are detected, see [Content policy and compliance](solution_overview#content_policy_and_compliance).

## Moderating assets on upload

To mark an image for Amazon Rekognition moderation:  

``` multi
|ruby 
Cloudinary::Uploader.upload("user_photo.jpg", 
  moderation: 'aws_rek')

|php_2
$cloudinary->uploadApi()->upload("user_photo.jpg",
  [ "moderation" => "aws_rek" ]);

|nodejs
cloudinary.v2.uploader
.upload("user_photo.jpg",
  { moderation: 'aws_rek' })
.then(result=>console.log(result)); 

|python
cloudinary.uploader.upload("user_photo.jpg",
  moderation = "aws_rek")

|java
cloudinary.uploader().upload("user_photo.jpg", 
  Cloudinary.asMap("moderation", "aws_rek"));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"user_photo.jpg"),
  Moderation = "aws_rek"};
var uploadResult = cloudinary.Upload(uploadParams); 

|go
resp, err := cld.Upload.Upload(ctx, "user_photo.jpg", uploader.UploadParams{
		Moderation: "aws_rek"})

|android
MediaManager.get().upload("user_photo.jpg")
  .option("moderation", "aws_rek").dispatch();

|swift
let params = CLDUploadRequestParams()
  .setModeration(.aws_rek)
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: "user_photo.jpg", params: params) 

|cli
cld uploader upload user_photo.jpg moderation=aws_rek

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=user_photo.jpg&moderation=aws_rek&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```
> **NOTE**: By default, assets that are marked for moderation are deliverable and available via the Media Library. If you'd like the assets marked for moderation to be blocked (until approved) either from the Media Library, or from being delivered, or from both, [contact support](https://support.cloudinary.com/hc/en-us/requests/new).
## Moderation response

The following snippet shows an example of a response to an upload API call, indicating the results of the request for moderation, and shows that the moderation result has put the image in 'rejected' status.

```json
{
...
 "moderation": 
  [{"response": 
     {"moderation_labels": 
       [{"confidence": 94.9907455444336,
         "name": "Suggestive",
         "parent_name": ""},
        {"confidence": 94.9907455444336,
         "name": "Female Swimwear Or Underwear",
         "parent_name": "Suggestive"}]},
    "status": "rejected",
    "kind": "aws_rek",
    "updated_at": "2017-08-03T08:26:58Z"}],
 ...
}
```

> **TIP**: For images, you can display a placeholder image instead of a rejected image using the `default_image` parameter (`d` for URLs) when delivering the image. See the [Using default image placeholders](advanced_url_delivery_options#using_a_default_image_placeholder) documentation for more details.

## Moderating existing assets

You can also request moderation for previously uploaded assets using the [explicit](image_upload_api_reference#explicit) API method. 

The following example requests Perception Point Malware Detection for the already uploaded image with a Public ID of `shirt` as follows: 

```multi
|ruby  
result = Cloudinary::Uploader
.explicit("shirt", 
  type: "upload",
  moderation: "perception_point")
 
|php_2
$result = $cloudinary->uploadApi()
->explicit("shirt", [
    "type" => "upload", 
    "moderation" => "perception_point"]);
 
|python
result = cloudinary.uploader\
.explicit("shirt", 
  type = "upload",
  moderation = "perception_point")


|nodejs
cloudinary.v2.uploader
.explicit("shirt", 
  { type: "upload",
	moderation: "perception_point"})
.then(result=>console.log(result)); 

  
|java
result = cloudinary.uploader()
.explicit("shirt", 
  ObjectUtils.asMap(
    "type", "upload",
    "moderation", "perception_point"));

|csharp
var explicitParams = new ExplicitParams("shirt"){
  Type = "upload",
  Moderation = "perception_point"};
var explicitResult = cloudinary.Explicit(explicitParams);

|go
resp, err := cld.Upload.Explicit(ctx, uploader.ExplicitParams{
    PublicID: "shirt", 
    Type: "upload", 
    Moderation: "perception_point"})

|dart
cloudinary.uploader().explicit(ExplicitParams("shirt",
    params: UploadParams(
        type: "upload",
        moderation: "perception_point")));

|swift
let params = CLDExplicitRequestParams().setModeration("perception_point")
let result = cloudinary.createManagementApi().explicit("shirt", params: params)

|curl
curl https://api.cloudinary.com/v1_1/demo/image/explicit -X POST --data 'type=upload&public_id=shirt&moderation=perception_point&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af' 

|cli
cld uploader explicit "shirt" type="upload" moderation="perception_point"
```

## Moderating assets manually

You can manually accept or reject assets that are uploaded to Cloudinary and marked for manual moderation. 

As some automatic moderations are based on a decision made by an advanced algorithm, in some cases you may want to manually override the moderation decision and either approve a previously rejected image or reject an approved one. You can manually override any decisions made automatically at any point in the moderation process. Afterwards, the asset will be considered manually moderated, regardless of whether the asset was originally marked for manual moderation.

### Moderating assets via the Media Library 

The roles required to moderate assets depend on your permissions system. Cloudinary is gradually rolling out Roles and Permissions — see [Roles and Permissions vs. legacy](user_provisioning#roles_and_permissions_vs_legacy) to find out which system you have and the differences.

* **In Roles and Permissions**: Admin-level [system roles](dam_admin_system_roles_permissions#global_product_environment_level_roles) (Master Admin, Admin, Tech Admin, and Media Library Admin) have full moderation access. Users with the **Media Library User** system role can moderate assets in folders where they have the **Editor** or **Manager** [folder role](dam_admin_system_roles_permissions#rp_moderation). Any user can also be granted moderation access via the **Moderator** [standalone global role](dam_admin_users_groups#ml_user_permissions), which is assignable to any user — not just Media Library Users. Enterprise customers can additionally grant moderation access via custom roles using the [Moderate all assets](dam_admin_system_roles_permissions#management_via_assets) (global) or [Moderate assets](dam_admin_system_roles_permissions#folder_permissions) (folder-level) permissions.
* **In the legacy permissions system**: Master admin, Media Library admin, and Technical admin [roles](dam_admin_users_groups#role_based_permissions) have full moderation access. Media Library users with the [Moderate asset](dam_admin_users_groups#ml_user_permissions) administrator permission can moderate assets in folders where they have **Can Edit** or **Can Manage** permissions.

To manually review assets, select **Moderation** in the [Media Library](/console/media_library) navigation pane. From there, you can browse moderated assets and decide to accept or reject them.

![Moderation page](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_black/v1667726089/docs/DAM/moderation_page.png "thumb: w_700,dpr_2, width: 700, popup:true")
   
If an asset is marked for multiple moderations, you can view its [moderation history](dam_admin_asset_management#moderation_history) to track its progress through the moderation process. 

For more information, see [Reviewing assets manually](dam_admin_asset_management#reviewing_assets_manually).

### Moderating assets via the Admin API
Alternatively to using the Media Library interface, you can use Cloudinary's Admin API to manually override the moderation result. The following example uses the [`update` API method](admin_api#update_details_of_an_existing_resource) while specifying a public ID of a moderated image and setting the `moderation_status` parameter to the `rejected` status.         
          
```multi
|ruby
Cloudinary::Api.update("hwepb67oxzh4lrigssld", 
  moderation_status: "rejected")

|php_2
$api->update("hwepb67oxzh4lrigssld", 
  ["moderation_status" => "rejected"]);

|python
cloudinary.api.update("hwepb67oxzh4lrigssld",
  moderation_status = "rejected")

|nodejs
cloudinary.v2.api
.update("hwepb67oxzh4lrigssld",
  { moderation_status: "rejected" })
.then(result=>console.log(result));
  
|java
cloudinary.api().update("hwepb67oxzh4lrigssld", 
  ObjectUtils.asMap("moderation_status", "rejected"));

|csharp
var updateParams = new UpdateParams("hwepb67oxzh4lrigssld")
{
  ModerationStatus = "rejected"
};
var updateResult = cloudinary.Update(updateParams); 

|go
resp, err := cld.Admin.UpdateAsset(ctx, admin.UpdateAssetParams{
		PublicID:         "hwepb67oxzh4lrigssld",
		ModerationStatus: "rejected"})

|cli
cld admin update "hwepb67oxzh4lrigssld" moderation_status="rejected"
```

## Moderation notifications

You can add a `notification_url` parameter while uploading or updating an asset, which instructs Cloudinary to [notify](notifications) your application of changes to moderation status, with the details of the moderation event (approval or rejection). For example:

```multi
|ruby  
Cloudinary::Uploader.upload("sample.jpg",
  moderation: "manual",
  notification_url: "https://mysite.example.com/mod_endpoint")
 
|php_2
$cloudinary->uploadApi()->upload("sample.jpg", [ 
    "moderation" => "manual",
    "notification_url" => "https://mysite.example.com/mod_endpoint"]);

|python
cloudinary.uploader.upload("sample.jpg", 
  moderation = "manual",
  notification_url = "https://mysite.example.com/mod_endpoint")

|nodejs
cloudinary.v2.uploader
.upload("sample.jpg", 
  { moderation: "manual",
    notification_url: "https://mysite.example.com/mod_endpoint" })
.then(result=>console.log(result)); 
  
|java
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "moderation", "manual",
    "notification_url", "https://mysite.example.com/mod_endpoint"));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Moderation = "manual",
  NotificationUrl = "https://mysite.example.com/mod_endpoint"};
var uploadResult = cloudinary.Upload(uploadParams);

|go
resp, err := cld.Upload.Upload(ctx, "sample.jpg", uploader.UploadParams{
		Moderation: "manual",
		NotificationURL: "https://mysite.example.com/mod_endpoint"})

|android
MediaManager.get().upload("sample.jpg")
  .option("moderation", "manual")
  .option("notification_url", "https://mysite.example.com/mod_endpoint").dispatch();

|swift
let params = CLDUploadRequestParams()
  .setModeration(.manual)
  .setNotificationUrl("https://mysite.example.com/mod_endpoint")
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 moderation=manual notification_url="https://mysite.example.com/mod_endpoint"

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=sample.jpg&moderation=manual&notification_url=https://mysite.example.com/mod_endpoint&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

## Multiple moderations

You can also mark an asset for more than one moderation in a single upload call. This might be useful if you want to reject an asset based on more than one criteria, for example, if it's either a duplicate or has inappropriate content. In that case, you might moderate the asset using the Amazon Rekognition AI Moderation as well as the Cloudinary Duplicate Image Detection add-ons. You should always add a notification URL when requesting multiple moderations.

An asset has a separate status for each moderation it's marked for: 

* `queued`: The asset is waiting for the moderation to be applied while preceding moderations are being applied first. 
* `pending`: The asset is in the process of being moderated but an outcome hasn't been reached yet.
* `approved` or `rejected`: The possible outcomes of the moderation.
* `aborted`: The asset has been rejected by another moderations that was applied to it. As a result, the final status for the asset is `rejected`, and this moderation won't be applied.

To use more than one moderation, set the `moderation` parameter to a string consisting of a pipe-separated list of the moderation types you want to apply. The order of your list dictates the order in which the moderations are applied. If included, `manual` moderation must be last. 

For the first moderation in the list, the status of the asset is set to `pending` immediately on upload, and for all the other moderations requested, the status is set to `queued`. If the first moderation is approved, the next moderation is started and its status is set to `pending`.

This process continues until either the asset is rejected by a moderation, in which case any moderations still queued are now `aborted` and the final moderation status is set to `rejected`, or until all of the moderations are applied and `approved`. In that case, the final moderation status of the asset is `approved`. 

In addition, a summary will be sent at the end of the moderation process informing you of the final outcome and the status of each individual moderation (`pending`, `aborted`, `approved` or `rejected`). 

For example, to mark an image for moderation by the Amazon Rekognition AI Moderation add-on and the Cloudinary Duplicate Image Detection add-on, and to request notifications when the moderations are completed:  

``` multi
|ruby 
Cloudinary::Uploader.upload("user_photo.jpg", 
  moderation: "aws_rek|duplicate:0",
  notification_url: "https://mysite.example.com/hooks")

|php_2
$cloudinary->uploadApi()->upload("user_photo.jpg",
  [ "moderation" => "aws_rek|duplicate:0",
  "notification_url" => "https://mysite.example.com/hooks" ]);

|nodejs
cloudinary.v2.uploader.upload("user_photo.jpg",
  { moderation: "aws_rek|duplicate:0",
    notification_url: "https://mysite.example.com/hooks" },
  function(error, result) { console.log(result, error); });

|python
cloudinary.uploader.upload("user_photo.jpg",
  moderation = "aws_rek|duplicate:0",
  notification_url = "https://mysite.example.com/hooks")

|java
cloudinary.uploader().upload("user_photo.jpg", 
  Cloudinary.asMap(
    "moderation", "aws_rek|duplicate:0",
    "notification_url", "https://mysite.example.com/hooks"));

|csharp
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"user_photo.jpg"),
  Moderation = "aws_rek|duplicate:0"
  NotificationUrl = "https://mysite.example.com/hooks"};
var uploadResult = cloudinary.Upload(uploadParams); 

|go
resp, err := cld.Upload.Upload(ctx, "user_photo.jpg", uploader.UploadParams{
		Moderation:      "aws_rek|duplicate:0",
    NotificationURL: "https://mysite.example.com/hooks"})

|android
MediaManager.get().upload("user_photo.jpg")
  .option("moderation", "aws_rek|duplicate:0")
  .option("notification_url", "https://mysite.example.com/hooks").dispatch();

|swift
let params = CLDUploadRequestParams()
  .setModeration(.manual)
  .setNotificationUrl("https://mysite.example.com/hooks")
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: "user_photo.jpg", params: params) 

|cli
cld uploader upload user_photo.jpg moderation="aws_rek|duplicate:0" notification_url="https://mysite.example.com/hooks"

|curl
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST --data 'file=user_photo.jpg&moderation=aws_rek|duplicate:0&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'
```

### Multiple notification responses

When you mark an asset for multiple moderations and request [notifications](notifications), messages will be sent to inform you of the outcome (`approved` or `rejected`) of each individual moderation when it resolves. In addition, a summary will be sent at the end of the moderation process informing you of the final outcome and the status of each individual moderation (`pending`, `aborted`, `approved` or `rejected`). 

* **If the asset was marked for manual moderation**: The summary with the asset's final status will only be sent once the user has manually approved or rejected the asset. Even if the asset is rejected by one of the automatic moderations, the asset status will remain pending until the manual moderation is complete. 
  
* **If the asset wasn't marked for manual moderation**: The summary will be sent either when the status of any one of the moderations changes to `rejected` (making the final status `rejected`), or as soon as the status of every one of the moderations is `approved` (making the final status `approved`).

## Video tutorial: Moderate images using the Node.js SDK

Watch this video tutorial to learn how to moderate images using the [Node.js SDK](node_integration):

  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.

### Tutorial contents This tutorial presents the following topics. Click a timestamp to jump to that part of the video.
### Automatic image moderation
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=0 :sec=00 :player=cld} | When you have thousands of images being uploaded to your site, moderating them manually isn't feasible. Instead, you can moderate them automatically using AI.
|

### Manual image moderation
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=0 :sec=14 :player=cld} | When using the [Node.js SDK](node_integration) upload call to upload an image, you can set the `moderation` parameter to `manual` (as shown below). This sets the `moderation` status to `pending` in the upload response. You can find assets pending manual moderation in the Cloudinary Console, in the **Moderation** page of the **Media Library**, with **Manual** selected. There, you can manually approve or reject the assets.
|

```nodejs
const results = await cloudinary.uploader.upload("./images/food.jpg", {
  moderation: "manual"
});
```

### Image moderation using Amazon Rekognition
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=1 :sec=13 :player=cld} | To moderate images automatically using Amazon Rekognition, first subscribe to the [Amazon Rekognition AI Moderation add-on](aws_rekognition_ai_moderation_addon), then set `moderation` to `aws_rek`. There are various [moderation categories](aws_rekognition_ai_moderation_addon#moderation_categorization) that you can [set thresholds for](aws_rekognition_ai_moderation_addon#request_image_moderation) in the upload call. Images are approved or rejected automatically based on the confidence threshold of the detected content. They are set to a 0.5 threshold by default.
|

```nodejs
const results = await cloudinary.uploader.upload("./images/food.jpg", {
  moderation: "aws_rek"
});
```

### Set automatic moderation in an upload preset
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=2 :sec=15 :player=cld} | You can use an [upload preset](upload_presets) to configure automatic moderation. In the **Upload** settings of your product environment, you can create an upload preset with **Amazon Rekognition** set and you can fine-tune the category thresholds to suit your needs.
|

