DEV Community

Cover image for NSFW Detection: API vs NudeNet for Content Moderation
AI Engine
AI Engine

Posted on • Originally published at ai-engine.net

NSFW Detection: API vs NudeNet for Content Moderation

Your platform accepts user-uploaded images. You need to filter out inappropriate content before it reaches other users. Two options: install NudeNet, the most popular open-source NSFW detection library (2,300+ GitHub stars), or call a cloud NSFW detection API that handles everything server-side. This guide tests both on the same images and compares what they catch, what they miss, and what it costs to run each in production.

Want to test on your own images? Try the NSFW Detect API on a few uploads.

Quick Comparison

NSFW Detect API NudeNet
Categories 10 (nudity, violence, drugs, alcohol, tobacco, gambling, hate symbols, etc.) 1 (nudity only)
Label structure Hierarchical (3 levels) Flat (body parts)
Setup API key pip install nudenet + ONNX model download
GPU Not needed Optional (faster)
Accuracy 93-98% across categories ~90% on nudity
License Commercial AGPL-3.0

What NudeNet Does

NudeNet is a Python library that detects nudity in images. Version 3 uses ONNX Runtime instead of TensorFlow, which makes it lighter and faster to install.

from nudenet import NudeDetector

detector = NudeDetector()
results = detector.detect("photo.jpg")

for detection in results:
    print(f"{detection['class']}: {detection['score']:.3f}")
    # FEMALE_BREAST_EXPOSED: 0.787
    # FACE_FEMALE: 0.736
Enter fullscreen mode Exit fullscreen mode

The detection classes are all body-part based: exposed/covered variants of breasts, buttocks, genitalia, belly, feet, armpits, and face. There are no classes for violence, drugs, alcohol, gambling, or any non-nudity content.

What the NSFW Detection API Does

The NSFW Detect API classifies images across 10 categories with hierarchical sub-labels.

import requests

url = "https://nsfw-detect3.p.rapidapi.com/nsfw-detect"
headers = {
    "x-rapidapi-host": "nsfw-detect3.p.rapidapi.com",
    "x-rapidapi-key": "YOUR_API_KEY",
}

with open("photo.jpg", "rb") as f:
    response = requests.post(url, headers=headers, files={"image": f})

labels = response.json()["body"]["ModerationLabels"]
for label in labels:
    print(f"{label['Name']}: {label['Confidence']:.1f}% (parent: {label['ParentName']})")
    # Drugs & Tobacco: 99.4% (parent: )
    # Smoking: 99.4% (parent: Drugs & Tobacco)
Enter fullscreen mode Exit fullscreen mode

The response uses a 3-level taxonomy. Here is the actual JSON for a smoking photo:

{
  "statusCode": 200,
  "body": {
    "ModerationLabels": [
      {
        "Name": "Drugs & Tobacco",
        "ParentName": "",
        "TaxonomyLevel": 1,
        "Confidence": 99.4
      },
      {
        "Name": "Drugs & Tobacco Paraphernalia & Use",
        "ParentName": "Drugs & Tobacco",
        "TaxonomyLevel": 2,
        "Confidence": 99.4
      },
      {
        "Name": "Smoking",
        "ParentName": "Drugs & Tobacco Paraphernalia & Use",
        "TaxonomyLevel": 3,
        "Confidence": 99.4
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

You walk down the tree to get more specific. Top-level "Drugs & Tobacco" tells you the broad category, "Smoking" tells you the exact behavior. Set different thresholds per category: strict on nudity, lenient on suggestive content.

See the full comparison with side-by-side test results, accuracy benchmarks, and code for both tools in the complete guide.


Testing Both on the Same Images

We tested both tools on three Pexels images (no explicit content).

Test 1: Male shirtless photo

  • API: Non-Explicit Nudity (99.9%), Exposed Male Nipple (99.9%). Correct category, correct gender.
  • NudeNet: FEMALE_BREAST_EXPOSED (78.7%), FACE_FEMALE (73.6%). Wrong gender on both detections. The image shows a man.

Test 2: Smoking photo

  • API: Drugs & Tobacco (99.4%), Smoking (99.4%). Correctly identifies smoking.
  • NudeNet: FACE_FEMALE (67.4%). No smoking detection. Also misclassifies the male face as female.

Test 3: Alcohol photo

  • API: Alcohol (98.6%), Alcoholic Beverages (98.6%). Identifies the beer glasses.
  • NudeNet: No detections. Alcohol is not in NudeNet's scope.

The Category Gap

The test results illustrate the fundamental difference. NudeNet is a nudity detector. The API is a content moderator covering 10 categories:

  • Explicit Nudity
  • Non-Explicit Nudity (swimwear, partial exposure)
  • Suggestive content
  • Violence
  • Visually Disturbing
  • Drugs & Tobacco
  • Alcohol
  • Gambling
  • Hate Symbols
  • Rude Gestures

For platforms with advertising revenue, brand safety requires all 10. An advertiser will not care that your filter catches nudity if their ad appears next to a photo of someone smoking or holding a weapon.

When to Choose NudeNet

  • Nudity-only filtering. If explicit nudity is your only concern, NudeNet covers it.
  • Offline or air-gapped environments. No network dependency.
  • Privacy-critical workloads. Images never leave your server.

When to Choose the API

  • Multi-category moderation. Drugs, alcohol, violence, hate symbols, gambling. NudeNet cannot help.
  • Brand safety. Advertising platforms need all 10 categories.
  • Scale without infrastructure. No GPU servers, no model updates.
  • Hierarchical filtering. Set different thresholds per category.

Running NudeNet in Production

Tutorials make NudeNet look simple: pip install nudenet, call detect(), done. In production:

  • AGPL-3.0 license. Requires you to open-source your application if you distribute it. For SaaS platforms, this is a legal grey area.
  • No model updates. NudeNet's model was last updated in 2023.
  • Gender accuracy. Our tests showed NudeNet misclassifying male subjects as female on 2 out of 3 images.

Sources


Read the full guide with side-by-side demos, all 10 category details, and JavaScript examples on ai-engine.net.

Top comments (0)