Flutter · React Native · Swift · Kotlin

On-device NSFW detection.
No uploads. No cloud.

Pass image bytes, get back labels, confidence scores, and bounding boxes. Everything runs on the user's device — images never leave the phone.

main.dart
// 1. initialize once (e.g. in main())
await XPunge.initialize('xp1.your-api-key');

// 2. analyze any image
final detections = await XPunge.analyzeImage(imageBytes);

// 3. use the results
for (final d in detections) {
  print('${d.label}${(d.confidence * 100).toInt()}%');
  print('box: ${d.boundingBox}');
}
5.1 MB
Model size
3%
Misclassification rate vs. 38% for ViT
1.6%
False positive rate on swimwear
1.23×
Gender FPR disparity (FAccT audit)
0 uploads
Images sent to any server

One API key. Every platform.

The same model, the same key, and the same privacy guarantee across your entire stack.

Flutter
Live
flutter pub add xpunge
pub.dev/packages/xpunge →
React Native
Live
npm install xpunge
npmjs.com/package/xpunge →
Native iOS
Live
github.com/markatlarge/xpunge-ios
Swift Package Manager →
Native Android
Live
com.xpunge:xpunge-android:0.1.0
GitHub Packages →
Why xPunge

Built for the constraint that matters most

The model runs entirely on-device via CoreML (iOS) and LiteRT (Android). That constraint isn't a tradeoff — it turned out to be an advantage.

🔒
True privacy
Images are processed locally and never transmitted. No server ever sees the content your users are analyzing.
Fast on-device inference
YOLO26n runs NMS-free with native end-to-end inference. ~39ms CPU latency. No network round-trip, no cold starts.
🎯
Anatomy detection, not scene classification
xPunge detects specific anatomical regions with bounding boxes — not "looks like NSFW." This eliminates the false positives that plague whole-image classifiers.
⚖️
Fairness-audited
Evaluated against the FAccT 2024 methodology. Gender FPR disparity ratio of 1.23× — lower than all models audited in the original Garcia et al. study.
📦
Tiny footprint
5.1 MB model — 17× smaller than InceptionV3 classifiers, 175× smaller than CLIP-based models. Ships inside your app bundle.
🧩
Simple, consistent API
Three methods on every platform: initialize(), analyzeImage(), analyzeFile(). Flutter, React Native — same key, same calls, same results.
📄
Benchmarks & fairness audit
Three independent evaluations — against Google Cloud Vision SafeSearch, a Vision Transformer classifier, and the FAccT 2024 fairness methodology — are documented in full. Read the paper →
📱
Want to see it in action first?
The model powering xPunge is live in Punge — a consumer app available on the App Store and Google Play. Try it on your own photos before you integrate.
Quickstart

Up and running in minutes

Get an API key from the developer dashboard, then add xPunge to your project.

1
Get an API key
Sign up at the developer dashboard. Register your app's bundle ID or package name. A free key (1,000 images/month) is issued immediately.
2
Add the dependency
In your pubspec.yaml, or run flutter pub add xpunge. Package on pub.dev →
pubspec.yaml
dependencies:
  xpunge: ^1.0.0
3
Initialize & detect
Call initialize() once at app start. Then analyzeImage() returns a list of Detection objects with label, confidence, and bounding box.
main.dart
import 'package:xpunge/xpunge.dart';

// In main() or app initialization
await XPunge.initialize('xp1.your-api-key');

// From bytes
List<Detection> results =
    await XPunge.analyzeImage(imageBytes);

// From a File
List<Detection> results =
    await XPunge.analyzeFile(file);

// From an XFile (image_picker, etc.)
List<Detection> results =
    await XPunge.analyzeXFile(xfile);
Detection class
class Detection {
  final String  label;        // e.g. 'breast'
  final double  confidence;   // 0.0 – 1.0
  final Rect    boundingBox;  // pixel coords
  // free tier: boundingBox = Rect.zero
}
1
Get an API key
Sign up at the developer dashboard. Register your app's bundle ID or package name. A free key (1,000 images/month) is issued immediately.
2
Install the package
Then for iOS run cd ios && pod install. Android links automatically. Package on npm →
terminal
npm install xpunge
3
Initialize & detect
Call initialize() once at app start. analyzeImage() takes a base64 string; analyzeFile() takes a file path.
App.tsx
import { initialize, analyzeImage, analyzeFile }
  from 'xpunge';

// Call once at app startup
await initialize('xp1.your-api-key');

// From base64
const detections = await analyzeImage(base64String);

// From file path
const detections = await analyzeFile('/path/to/image.jpg');
Detection interface
interface Detection {
  label:      'breast' | 'penis' | 'anus'
            | 'rear' | 'vagina';
  confidence: number;  // 0.0 – 1.0
  x:          number;  // normalized 0.0 – 1.0
  y:          number;
  width:      number;
  height:     number;
  // free tier: x, y, width, height = 0
}
1
Get an API key
Sign up at the developer dashboard. Register your app's bundle ID. A free key (1,000 images/month) is issued immediately.
2
Add via Swift Package Manager
In Xcode: File → Add Package Dependencies and enter the repo URL. Requires iOS 14.0+ and Xcode 15+. GitHub →
Package.swift
dependencies: [
  .package(
    url: "https://github.com/markatlarge/xpunge-ios",
    from: "0.1.0"
  ),
]
3
Initialize & detect
Create one XpungeDetector instance, call initialize(apiKey:) once, then call analyzeImage() or analyzeFile() anywhere.
ContentView.swift
import XpungeSDK

let detector = XpungeDetector()

// Initialize once
try detector.initialize(apiKey: "xp1.your-api-key")

// From image Data (JPEG, PNG, HEIF, WebP)
let detections = detector.analyzeImage(imageData)

// From a file path
let detections = detector.analyzeFile(path: "/path/to/image.jpg")

for d in detections {
  print("\(d.label) \(Int(d.confidence * 100))%")
  print("at (\(d.x), \(d.y))")
}
Detection struct
struct Detection {
  let label:      String  // "breast" | "penis" | ...
  let confidence: Double  // 0.0–1.0
  let x:          Double  // normalized 0–1
  let y:          Double
  let width:      Double
  let height:     Double
  // free tier: x, y, width, height = 0
}
1
Get an API key
Sign up at the developer dashboard. Register your app's package name. A free key (1,000 images/month) is issued immediately.
2
Add via Gradle
Hosted on GitHub Packages — add the repo and dependency below. Requires a GitHub token with read:packages scope. Requires minSdkVersion 24. GitHub →
build.gradle
// project-level build.gradle
repositories {
  maven {
    url = uri("https://maven.pkg.github.com/markatlarge/xpunge-android")
    credentials {
      username = System.getenv("GITHUB_USERNAME")
      password = System.getenv("GITHUB_TOKEN")
    }
  }
}

// app-level build.gradle
dependencies {
  implementation 'com.xpunge:xpunge-android:0.1.0'
}
3
Initialize & detect
Create one XpungeDetector, call initialize() once (typically in your ViewModel or Application class), then call analyzeFile() or analyzeImage().
MainActivity.kt
import com.xpunge.android.XpungeDetector

val detector = XpungeDetector(context)

// Initialize once
detector.initialize("xp1.your-api-key")

// From a file path
val detections = detector.analyzeFile("/path/to/image.jpg")

// From raw bytes (JPEG, PNG, HEIF, WebP)
val detections = detector.analyzeImage(imageByteArray)

for (d in detections) {
  Log.d("xPunge", "${d.label} ${(d.confidence*100).toInt()}%")
}

// Release when done
detector.dispose()
Detection data class
data class Detection(
  val label:      String,  // "breast" | "penis" | ...
  val confidence: Double,  // 0.0–1.0
  val x:          Double,  // normalized 0–1
  val y:          Double,
  val width:      Double,
  val height:     Double,
  // free tier: x, y, width, height = 0.0
)

Start free. Scale when you're ready.

Priced per image — cheaper than Google Cloud Vision at every tier. All paid plans include full bounding boxes, video frame analysis, and email support.

Free
$0
forever
1,000
images / month
Get started
Basic
$29
/ month
50,000
images / month · $0.00058 / img
Subscribe
Growth
$149
/ month
500,000
images / month · $0.00030 / img
Subscribe
Scale
$499
/ month
5,000,000
images / month · $0.00010 / img
Subscribe
Enterprise
Custom
 
5M+
images / month · negotiated
Contact us
All plans billed monthly. Cancel anytime via the Stripe customer portal.
Google Cloud Vision SafeSearch costs $0.0015/image at every volume.