The Advanced Nudity Detection API is an A.I.-based service to determine the nudity content of images and videos. The model returns a total of 29 classes. 7 intensity classes to provide you with an overall classification of the image, 19 suggestive classes to give you a more fine-grained understanding of the content in the case of suggestive content, and 3 context classes that you can use to automatically understand the content of your images/videos, and set the appropriate rules.
Here are the 7 intensity classes from the most explicit to the least explicit:
Intensity classes | Sexual Activity | sexual_activity |
Sexual Display | sexual_display | |
Erotica | erotica | |
Very suggestive | very_suggestive | |
Suggestive | suggestive | |
Mildly suggestive | mildly_suggestive | |
None | none |
Here are the 19 suggestive classes that can be used to further refine your filtering:
Suggestive classes | Visibly undressed | visibly_undressed |
Sextoy | sextoy | |
Suggestive focus | suggestive_focus | |
Suggestive pose | suggestive_pose | |
Female underwear | lingerie | |
Male underwear | male_underwear | |
Very revealing cleavage | cleavage_categories.very_revealing | |
Revealing cleavage | cleavage_categories.revealing | |
Very revealing male chest | male_chest_categories.very_revealing | |
Revealing male chest | male_chest_categories.revealing | |
Slightly revealing male chest | male_chest_categories.slightly_revealing | |
Nudity art | nudity_art | |
Schematic | schematic | |
Bikini | bikini | |
One-piece swimwear | swimwear_one_piece | |
Male swimwear | swimwear_male | |
Minishort | minishort | |
Miniskirt | miniskirt | |
Other suggestive scene or pose | other |
Here are the 3 context classes that can be used to further refine your filtering:
Context classes | Sea, lake, pool | sea_lake_pool |
Other outdoor | outdoor_other | |
Other indoor | indoor_other |
Intensity classes are organized from the most explicit (sexual activity) to the least explicit (mildly suggestive).
The scores are inclusive, meaning that if an image triggers an intensity level, the levels below will also be triggered. Example: if an image contains erotica, it will lead to high scores for erotica, very_suggestive, suggestive and mildly_suggestive.
Suggestive classes can give you a more fine-grained description of the image content. This is useful when the image triggers the very_suggestive, suggestive or mildly_suggestive classes.
Some moderation decisions need to be based on context. As an example, shirtless men or women in bikinis might be moderated differently if they are at the beach or in their bathroom.
To help you perform such fine-grained decisions, additional context information is available with the following classes:
If you haven't already, create an account to get your own API keys.
Let's say you want to moderate the following image:
You can either share a URL to the image, or upload the raw binary image.
Here's how to proceed if you choose to share the image URL:
curl -X GET -G 'https://api.sightengine.com/1.0/check.json' \
-d 'models=nudity-2.1' \
-d 'api_user={api_user}&api_secret={api_secret}' \
--data-urlencode 'url=https://sightengine.com/assets/img/examples/example-fac-1000.jpg'
# this example uses requests
import requests
import json
params = {
'url': 'https://sightengine.com/assets/img/examples/example-fac-1000.jpg',
'models': 'nudity-2.1',
'api_user': '{api_user}',
'api_secret': '{api_secret}'
}
r = requests.get('https://api.sightengine.com/1.0/check.json', params=params)
output = json.loads(r.text)
$params = array(
'url' => 'https://sightengine.com/assets/img/examples/example-fac-1000.jpg',
'models' => 'nudity-2.1',
'api_user' => '{api_user}',
'api_secret' => '{api_secret}',
);
// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/check.json?'.http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$output = json_decode($response, true);
// this example uses axios
const axios = require('axios');
axios.get('https://api.sightengine.com/1.0/check.json', {
params: {
'url': 'https://sightengine.com/assets/img/examples/example-fac-1000.jpg',
'models': 'nudity-2.1',
'api_user': '{api_user}',
'api_secret': '{api_secret}',
}
})
.then(function (response) {
// on success: handle response
console.log(response.data);
})
.catch(function (error) {
// handle error
if (error.response) console.log(error.response.data);
else console.log(error.message);
});
See request parameter description
Parameter | Type | Description |
media | binary | image to analyze |
models | string | comma-separated list of models to apply |
api_user | string | your API user id |
api_secret | string | your API secret |
Here's how to proceed if you choose to upload the raw image:
curl -X POST 'https://api.sightengine.com/1.0/check.json' \
-F 'media=@/path/to/image.jpg' \
-F 'models=nudity-2.1' \
-F 'api_user={api_user}' \
-F 'api_secret={api_secret}'
# this example uses requests
import requests
import json
params = {
'models': 'nudity-2.1',
'api_user': '{api_user}',
'api_secret': '{api_secret}'
}
files = {'media': open('/path/to/image.jpg', 'rb')}
r = requests.post('https://api.sightengine.com/1.0/check.json', files=files, data=params)
output = json.loads(r.text)
$params = array(
'media' => new CurlFile('/path/to/image.jpg'),
'models' => 'nudity-2.1',
'api_user' => '{api_user}',
'api_secret' => '{api_secret}',
);
// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/check.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);
$output = json_decode($response, true);
// this example uses axios and form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
data = new FormData();
data.append('media', fs.createReadStream('/path/to/image.jpg'));
data.append('models', 'nudity-2.1');
data.append('api_user', '{api_user}');
data.append('api_secret', '{api_secret}');
axios({
method: 'post',
url:'https://api.sightengine.com/1.0/check.json',
data: data,
headers: data.getHeaders()
})
.then(function (response) {
// on success: handle response
console.log(response.data);
})
.catch(function (error) {
// handle error
if (error.response) console.log(error.response.data);
else console.log(error.message);
});
See request parameter description
Parameter | Type | Description |
media | binary | image to analyze |
models | string | comma-separated list of models to apply |
api_user | string | your API user id |
api_secret | string | your API secret |
The API will then return a JSON response with the following structure:
{
"status": "success",
"request": {
"id": "req_1SJJxJjUHnSVWreApx9fF",
"timestamp": 1693574119.571633,
"operations": 1
},
"nudity": {
"sexual_activity": 0.01,
"sexual_display": 0.01,
"erotica": 0.01,
"very_suggestive": 0.01,
"suggestive": 0.01,
"mildly_suggestive": 0.01,
"suggestive_classes": {
"bikini": 0.01,
"cleavage": 0.01,
"cleavage_categories": {
"very_revealing": 0.01,
"revealing": 0.01,
"none": 0.99
},
"lingerie": 0.01,
"male_chest": 0.01,
"male_chest_categories": {
"very_revealing": 0.01,
"revealing": 0.01,
"slightly_revealing": 0.01,
"none": 0.99
},
"male_underwear": 0.01,
"miniskirt": 0.01,
"other": 0.01,
"minishort": 0.11,
"nudity_art": 0.01,
"schematic": 0.01,
"sextoy": 0.01,
"suggestive_focus": 0.01,
"suggestive_pose": 0.01,
"swimwear_male": 0.01,
"swimwear_one_piece": 0.01,
"visibly_undressed": 0.01
},
"none": 0.99,
"context": {
"sea_lake_pool": 0.01,
"outdoor_other": 0.99,
"indoor_other": 0.01
}
},
"media": {
"id": "med_1SJJEFuLqeSedThQjhNoS",
"uri": "https://sightengine.com/assets/img/examples/example-fac-1000.jpg"
}
}
You can use the classes under the nudity object to determine the nudity level of the image. In the above example, nudity.none has a confidence of 0.99, meaning that the image does not contain nudity.
Here's how to proceed to analyze a short video (less than 1 minute):
curl -X POST 'https://api.sightengine.com/1.0/video/check-sync.json' \
-F 'media=@/path/to/video.mp4' \
-F 'models=nudity-2.1' \
-F 'api_user={api_user}' \
-F 'api_secret={api_secret}'
# this example uses requests
import requests
import json
params = {
# specify the models you want to apply
'models': 'nudity-2.1',
'api_user': '{api_user}',
'api_secret': '{api_secret}'
}
files = {'media': open('/path/to/video.mp4', 'rb')}
r = requests.post('https://api.sightengine.com/1.0/video/check-sync.json', files=files, data=params)
output = json.loads(r.text)
$params = array(
'media' => new CurlFile('/path/to/video.mp4'),
// specify the models you want to apply
'models' => 'nudity-2.1',
'api_user' => '{api_user}',
'api_secret' => '{api_secret}',
);
// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check-sync.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);
$output = json_decode($response, true);
// this example uses axios and form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
data = new FormData();
data.append('media', fs.createReadStream('/path/to/video.mp4'));
// specify the models you want to apply
data.append('models', 'nudity-2.1');
data.append('api_user', '{api_user}');
data.append('api_secret', '{api_secret}');
axios({
method: 'post',
url:'https://api.sightengine.com/1.0/video/check-sync.json',
data: data,
headers: data.getHeaders()
})
.then(function (response) {
// on success: handle response
console.log(response.data);
})
.catch(function (error) {
// handle error
if (error.response) console.log(error.response.data);
else console.log(error.message);
});
See request parameter description
Parameter | Type | Description |
media | binary | image to analyze |
models | string | comma-separated list of models to apply |
interval | float | frame interval in seconds, out of 0.5, 1, 2, 3, 4, 5 (optional) |
api_user | string | your API user id |
api_secret | string | your API secret |
Here's how to proceed to analyze a long video. Note that if the video file is very large, you might first need to upload it through the Upload API.
curl -X POST 'https://api.sightengine.com/1.0/video/check.json' \
-F 'media=@/path/to/video.mp4' \
-F 'models=nudity-2.1' \
-F 'callback_url=https://yourcallback/path' \
-F 'api_user={api_user}' \
-F 'api_secret={api_secret}'
# this example uses requests
import requests
import json
params = {
# specify the models you want to apply
'models': 'nudity-2.1',
# specify where you want to receive result callbacks
'callback_url': 'https://yourcallback/path',
'api_user': '{api_user}',
'api_secret': '{api_secret}'
}
files = {'media': open('/path/to/video.mp4', 'rb')}
r = requests.post('https://api.sightengine.com/1.0/video/check.json', files=files, data=params)
output = json.loads(r.text)
$params = array(
'media' => new CurlFile('/path/to/video.mp4'),
// specify the models you want to apply
'models' => 'nudity-2.1',
// specify where you want to receive result callbacks
'callback_url' => 'https://yourcallback/path',
'api_user' => '{api_user}',
'api_secret' => '{api_secret}',
);
// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);
$output = json_decode($response, true);
// this example uses axios and form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
data = new FormData();
data.append('media', fs.createReadStream('/path/to/video.mp4'));
// specify the models you want to apply
data.append('models', 'nudity-2.1');
// specify where you want to receive result callbacks
data.append('callback_url', 'https://yourcallback/path');
data.append('api_user', '{api_user}');
data.append('api_secret', '{api_secret}');
axios({
method: 'post',
url:'https://api.sightengine.com/1.0/video/check.json',
data: data,
headers: data.getHeaders()
})
.then(function (response) {
// on success: handle response
console.log(response.data);
})
.catch(function (error) {
// handle error
if (error.response) console.log(error.response.data);
else console.log(error.message);
});
See request parameter description
Parameter | Type | Description |
media | binary | image to analyze |
callback_url | string | callback URL to receive moderation updates (optional) |
models | string | comma-separated list of models to apply |
interval | float | frame interval in seconds, out of 0.5, 1, 2, 3, 4, 5 (optional) |
api_user | string | your API user id |
api_secret | string | your API secret |
Here's how to proceed to analyze a live-stream:
curl -X GET -G 'https://api.sightengine.com/1.0/video/check.json' \
--data-urlencode 'stream_url=https://domain.tld/path/video.m3u8' \
-d 'models=nudity-2.1' \
-d 'callback_url=https://your.callback.url/path' \
-d 'api_user={api_user}' \
-d 'api_secret={api_secret}'
# if you haven't already, install the SDK with 'pip install sightengine'
from sightengine.client import SightengineClient
client = SightengineClient('{api_user}','{api_secret}')
output = client.check('nudity-2.1').video('https://domain.tld/path/video.m3u8', 'https://your.callback.url/path')
// if you haven't already, install the SDK with 'composer require sightengine/client-php'
use \Sightengine\SightengineClient;
$client = new SightengineClient('{api_user}','{api_secret}');
$output = $client->check(['nudity-2.1'])->video('https://domain.tld/path/video.m3u8', 'https://your.callback.url/path');
// if you haven't already, install the SDK with 'npm install sightengine --save'
var sightengine = require('sightengine')('{api_user}', '{api_secret}');
sightengine.check(['nudity-2.1']).video('https://domain.tld/path/video.m3u8', 'https://your.callback.url/path').then(function(result) {
// The API response (result)
}).catch(function(err) {
// Handle error
});
See request parameter description
Parameter | Type | Description |
stream_url | string | URL of the video stream |
callback_url | string | callback URL to receive moderation updates (optional) |
models | string | comma-separated list of models to apply |
interval | float | frame interval in seconds, out of 0.5, 1, 2, 3, 4, 5 (optional) |
api_user | string | your API user id |
api_secret | string | your API secret |
The Moderation result will be provided either directly in the request response (for sync calls, see below) or through the callback URL your provided (for async calls).
Here is the structure of the JSON response with moderation results for each analyzed frame under the data.frames array:
{
"status": "success",
"request": {
"id": "req_gmgHNy8oP6nvXYaJVLq9n",
"timestamp": 1717159864.348989,
"operations": 21
},
"data": {
"frames": [
{
"info": {
"id": "med_gmgHcUOwe41rWmqwPhVNU_1",
"position": 0
},
"nudity": {
"sexual_activity": 0.01,
"sexual_display": 0.01,
"erotica": 0.01,
"very_suggestive": 0.01,
"suggestive": 0.01,
"mildly_suggestive": 0.03,
"suggestive_classes": {
"bikini": 0.01,
"cleavage": 0.01,
"cleavage_categories": {
"very_revealing": 0.01,
"revealing": 0.01,
"none": 0.99
},
"lingerie": 0.01,
"male_chest": 0.01,
"male_chest_categories": {
"very_revealing": 0.01,
"revealing": 0.01,
"slightly_revealing": 0.01,
"none": 0.99
},
"male_underwear": 0.01,
"miniskirt": 0.01,
"minishort": 0.01,
"nudity_art": 0.01,
"schematic": 0.01,
"sextoy": 0.01,
"suggestive_focus": 0.01,
"suggestive_pose": 0.01,
"swimwear_male": 0.01,
"swimwear_one_piece": 0.01,
"visibly_undressed": 0.01,
"other": 0.01
},
"none": 0.97,
"context": {
"sea_lake_pool": 0.02,
"outdoor_other": 0.15,
"indoor_other": 0.83
}
}
},
...
]
},
"media": {
"id": "med_gmgHcUOwe41rWmqwPhVNU",
"uri": "yourfile.mp4"
},
}
You can use the classes under the nudity object to determine the nudity level of the video. In the above example, nudity.none has a confidence of 0.99, meaning that the video does not contain nudity.
See our full list of Image/Video models for details on other filters and checks you can run on your images and videos. You might also want to check our Text models to moderate text-based content: messages, reviews, comments, usernames...
Was this page helpful?