Skip to main content

opennsfw-onnx

Yahoo open_nsfw NSFW image classification, running on onnxruntime — no TensorFlow required.

License: Apache-2.0 PyPI Python

What & why

opennsfw-onnx runs Yahoo's open_nsfw ResNet-50 model through onnxruntime, giving you a small, modern classifier for whether an image is safe-for-work with no TensorFlow dependency and no GPU required (though GPU/CoreML acceleration is supported).

It exists because the previously-maintained opennsfw-standalone package has stalled — it pins ancient, CVE-affected dependencies (pillow<9, numpy<2) and hasn't been updated in years. opennsfw-onnx is a maintained, Apache-2.0 replacement that:

  • under CPUExecutionProvider, matches opennsfw-standalone's scores to within 1e-6 (observed 0.0 on the test fixtures) (see Performance),
  • is a near drop-in migration — one import line changes,
  • ships a modern API (NSFWClassifier, Prediction) plus a CLI,
  • accepts paths, bytes, file-like objects, PIL.Image, and numpy.ndarray as input,
  • supports batch inference and hardware acceleration (CUDA, TensorRT, DirectML, CoreML) via onnxruntime execution providers.

Install

pip install opennsfw-onnx

# with the CLI (typer)
pip install "opennsfw-onnx[cli]"

# with runtime model download-and-cache support (platformdirs)
pip install "opennsfw-onnx[download]"

Or with uv:

uv add opennsfw-onnx
uv add "opennsfw-onnx[cli]"

The ONNX model weight (~22.5 MB) ships bundled inside the wheel by default, so no separate download is required for typical installs.

Quickstart

from opennsfw_onnx import NSFWClassifier

clf = NSFWClassifier()

# Any of these work: a path, raw bytes, a file-like object, a PIL.Image, or an ndarray.
pred = clf.classify("photo.jpg")

print(pred.nsfw, pred.sfw)      # P(nsfw), P(sfw) — floats that sum to ~1.0
print(pred.is_nsfw)             # bool, using the classifier's threshold (default 0.5)
print(float(pred))              # Prediction supports __float__ -> P(nsfw)

# Classify many images at once (preprocessing is parallelized across a thread pool).
preds = clf.classify_batch(["a.jpg", "b.jpg", "c.jpg"])

# One-off classification without managing a classifier instance.
from opennsfw_onnx import classify
pred = classify("photo.jpg")

Prediction is a frozen dataclass with fields sfw: float, nsfw: float, threshold: float = 0.5, a computed is_nsfw: bool property, and a __float__ method returning nsfw.

Drop-in migration from opennsfw-standalone

If you're using opennsfw-standalone, migrating is a one-line import change — .load() and .infer(bytes) -> float behave identically:

# before
from opennsfw_standalone import OpenNSFWInferenceRunner

# after
from opennsfw_onnx.compat import OpenNSFWInferenceRunner

runner = OpenNSFWInferenceRunner.load()
score = runner.infer(image_bytes)   # float, P(nsfw)
opennsfw-standalone opennsfw-onnx
from opennsfw_standalone import OpenNSFWInferenceRunner from opennsfw_onnx.compat import OpenNSFWInferenceRunner
OpenNSFWInferenceRunner.load(model_path=None) OpenNSFWInferenceRunner.load(model_path=None) (identical signature)
runner.infer(image_bytes: bytes) -> float runner.infer(image_bytes: bytes) -> float (identical signature)
TensorFlow backend onnxruntime backend (CPU by default, accelerable)
pinned pillow<9, numpy<2 current pillow, numpy

Everything else about your code stays the same. For new code, prefer the richer NSFWClassifier API described above.

CLI

Install with the cli extra, then:

opennsfw-onnx classify photo.jpg
#     nsfw       sfw  verdict  path
#   0.0123    0.9877  sfw      photo.jpg

opennsfw-onnx classify "photos/*.jpg" --json
opennsfw-onnx classify photo.jpg --threshold 0.3
opennsfw-onnx classify photo.jpg --fast              # skip the JPEG round-trip for speed
opennsfw-onnx classify photo.jpg --provider CPUExecutionProvider

Flags:

Flag Description
-t, --threshold FLOAT NSFW decision threshold (default 0.5).
-j, --json Emit a JSON array of {path, nsfw, sfw, is_nsfw} instead of a text table.
--fast Skip the JPEG re-encode round-trip (jpeg_reencode=False) for faster, slightly less exact scores.
--provider Restrict/override the onnxruntime execution provider(s); repeatable.

Arguments accept file paths and shell-style globs (expanded internally, so quote globs to avoid premature shell expansion). Exit codes: 0 if no image is NSFW, 1 if any image is NSFW, 2 if no files matched.

Performance

  • Provider selection: by default, NSFWClassifier auto-selects the fastest available onnxruntime execution provider, preferring CUDAExecutionProvider → TensorrtExecutionProvider → DmlExecutionProvider → CoreMLExecutionProvider → CPUExecutionProvider, filtered to whatever's actually installed. Pass providers=[...] to pin a specific provider or ordering.
  • Fidelity vs. providers: on CPUExecutionProvider, opennsfw-onnx matches the original opennsfw-standalone scores to within 1e-6 (observed 0.0 on the test fixtures, verified against committed reference scores). Accelerated providers (CoreML, CUDA) can differ by up to ~5e-4 due to backend math differences — negligible for a 0–1 score decided at a 0.5 threshold, but pin providers=["CPUExecutionProvider"] if you need to reproduce the legacy scores. See docs/performance.md for details.
  • jpeg_reencode (default True): applies the reference JPEG round-trip during preprocessing for exact score reproduction. Set jpeg_reencode=False (or CLI --fast) to skip it — faster, with scores shifting by less than 1e-2.
  • Batch inference: classify_batch() preprocesses images in parallel across a thread pool (max_workers configurable) and runs them through the model as a single stacked batch.
  • warmup(): call clf.warmup() after constructing a classifier to run one dummy inference and avoid paying first-call initialization cost during real workloads.
  • Thread pinning: pass intra_op_num_threads=N to the constructor to control onnxruntime's intra-op thread pool size.

See docs/performance.md for a runnable benchmark snippet.

Model resolution

NSFWClassifier resolves the ONNX model file in this order, verifying its sha256 at every step (hard failure on mismatch):

  1. an explicit model_path argument,
  2. the OPENNSFW_ONNX_MODEL_PATH environment variable,
  3. the model bundled inside the installed wheel,
  4. as a last resort, downloading and caching it (requires the download extra).

See docs/api.md for the full reference.

Provenance & credits

  • The model weights are Yahoo's open_nsfw (BSD-2-Clause, Copyright (c) 2016 Yahoo Inc.), converted to ONNX.
  • The image preprocessing pipeline and the opennsfw_onnx.compat API are derived from opennsfw-standalone (MIT, Copyright (c) 2017 Sector Labs).

Full license texts and lineage are in NOTICE and THIRD_PARTY_LICENSES/. See also docs/provenance.md for the model's origin, extraction chain, and checksum.

License

Apache-2.0. See LICENSE.

Metadata

Release files for opennsfw-onnx 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for opennsfw-onnx 0.1.0
File Size Uploaded Provenance Actions
opennsfw_onnx-0.1.0.tar.gz 22.0 MB With provenance Details for opennsfw_onnx-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for opennsfw-onnx 0.1.0
File Interpreter ABI Platform Actions
opennsfw_onnx-0.1.0-py3-none-any.whl Python 3 none any Details for opennsfw_onnx-0.1.0-py3-none-any.whl

Total release size: 44.0 MB

Release files / opennsfw_onnx-0.1.0.tar.gz

Download URL opennsfw_onnx-0.1.0.tar.gz
Size 22.0 MB
Tags Source
SHA-256 checksum
How to use checksums
9419f0ef76d2cd28538476a0cc9d9d928e65e6929660f6f9f1b7447567a2d96d
BLAKE2b-256 checksum
How to use checksums
f27ce7bd2a51f491a811eef6a85bb8cccf69d6e9f159d14d2475cf5783061ba0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

Release files / opennsfw_onnx-0.1.0-py3-none-any.whl

Download URL opennsfw_onnx-0.1.0-py3-none-any.whl
Size 22.0 MB
Tags Python 3
SHA-256 checksum
How to use checksums
1d060aaba48c92c0f510f2ae29ddbbd98d43daf00877f5b5c253e34e6502f5bd
BLAKE2b-256 checksum
How to use checksums
9f6cd86945ffa011d97e149d15cc7f22fb8eea5f79fd15db5f5f22c09b964ec6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

Security for opennsfw-onnx 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for opennsfw_onnx-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page