M1chlCZ/nsfw_sherlock

Free, self-hosted image moderation API in Go. Check NSFW images on your own server with HTTP, gRPC, Docker, and optional OCR. No subscription or per-image API fees.

Go

29

127 commits

updated Oct 14, 2026

See the code

README

NSFW Sherlock logo: a magnifying glass over an image

NSFW Sherlock

Free, self-hosted image moderation.
Run it on your server. Keep image analysis local.

License: AGPL Docker Hub

NSFW Sherlock is a free, open-source API that checks images for NSFW content on your own hardware. It has no subscription or per-image API fees. You cover your own hardware and hosting costs.

  • Self-hosted: Image analysis runs on your server, without an external moderation API.
  • Easy to connect: Use HTTP or gRPC from your application.
  • Image checks: Classify photos and anime, and detect explicit regions.
  • Optional OCR: Use Tesseract to detect words in images.
  • Docker: Start with one command on Linux amd64 or arm64.

One Go binary runs the models with ONNX Runtime. The code uses AGPL-3.0. Model licenses apply separately.

Run with Docker

Run the CPU image:

docker run -e APP_ENV=web -p 4000:4000 m1chl/nsfw-sherlock

Make sure that the service responds:

curl http://localhost:4000/ping

The image includes the models and OCR support. It supports Linux amd64 and arm64. Docker Hub and GHCR publish the same images.

For gRPC, set APP_ENV=grpc. The default interface is HTTP.

Run a release binary

The releases page has archives for Linux amd64, Linux arm64, and macOS arm64, with checksums. The binaries do not include OCR support.

Clone the repository and unpack the archive into it. Then download the models and the runtime:

scripts/fetch-models.sh --ort-only
scripts/fetch-models.sh
./nsfw-sherlock

API

All image endpoints accept this JSON request:

{"base64":"<base64-encoded image>","filename":"image.jpg"}
HTTP endpointResponse
GET /pingService status
POST /pic/checknsfwPic and nsfwText flags
POST /pic/labelsProbabilities for drawings, hentai, neutral, porn, and sexy
POST /pic/analyzeFull analysis, model scores, region detections, and elapsed time

Example response from /pic/check:

{"status":"ok","message":"success","nsfwText":false,"nsfwPic":false}

The full analysis includes a verdict (sfw, suggestive, or explicit) and an nsfw score. Errors use {"errorMessage":"...","status":"FAIL","hasError":true}.

The gRPC service exposes Detect, DetectLabels, and Analyze. The service definition contains the request and response types.

GPU support

NVIDIA · CUDA

Install an NVIDIA driver compatible with CUDA 12.9 and the NVIDIA Container Toolkit. Then run the CUDA image:

docker run --gpus all -p 4000:4000 m1chl/nsfw-sherlock:v1.0.5-cuda

This image supports Linux amd64. It includes ONNX Runtime 1.29.0, CUDA 12, and cuDNN. ORT_DEVICE_ID selects the GPU index, with 0 as the default.

AMD · ROCm / MIGraphX

Install ROCm and a MIGraphX-enabled ONNX Runtime 1.29.0 shared library. Set ORT_PROVIDER=rocm. Point ORT_LIB to that library. Keep the provider libraries beside it. Add the ROCm dependencies to the library search path.

The rocm value is an alias for migraphx. The Go binding requires ORT API 29. Older runtimes are incompatible. This project does not publish an AMD image. The MIGraphX guide describes the runtime build.

If the selected provider is unavailable, the service stops at startup. Unsupported operators can still use the CPU. GPU inference remains untested on physical NVIDIA or AMD hardware.

Configuration

VariableDefaultPurpose
APP_ENVwebHTTP (web) or gRPC (grpc). http is a deprecated alias.
PORT4000Service port
NSFW_PROFILEbalancedModel profile
ORT_PROVIDERcpucpu, cuda, or migraphx. rocm aliases migraphx.
ORT_DEVICE_ID0GPU index
OCR_ENABLEDtrueText detection. Requires a build with OCR support.
Paths, limits, and logging
VariableDefaultPurpose
MODELS_DIR./assets/modelsModel directory
MANIFESTmodels/manifest.jsonModel manifest
ORT_LIBAuto-detectedONNX Runtime shared library path
BAD_WORDS_FILEAuto-detectedOCR word list. Uses an embedded list as a fallback.
MAX_IMAGE_BYTES20971520 (20 MiB)Maximum image size
MAX_IMAGE_PIXELS50000000Maximum decoded pixel count
SESSION_POOL_SIZE2Sessions per model
NSFW_ALLOW_DEGRADEDfalseAllow startup after a required model fails to load.
LOG_LEVELinfodebug, info, warn, or error
LOG_FORMATtexttext or json

Docker images supply the model and runtime paths. They use JSON logs.

Model profiles

ProfilePhoto modelAnime modelRegion detector
balanced (default)Freepik EVA02CaFormerNudeNet 320px
maxFreepik EVA02CaFormerNudeNet 640px
fastFreepik EVA02MobileNetV3NudeNet 320px
compatViT5 with five legacy labelsNoneNone

Build from source

Requirements: Go 1.27, a C compiler, Python 3, and curl. The runtime download supports Linux amd64, Linux arm64, and macOS arm64.

Download the source, runtime, and models. Then build the binary. Run the binary:

git clone https://github.com/M1chlCZ/nsfw_sherlock
cd nsfw_sherlock
scripts/fetch-models.sh --ort-only
scripts/fetch-models.sh
go build .
./nsfw_sherlock

The download script uses pinned SHA-256 digests for the runtime and models. The engine also compares each model digest with the manifest at startup. This source build excludes OCR and always reports nsfwText: false.

For OCR support, install Tesseract, Leptonica, their development libraries, and the English language data. Then build with the OCR tag:

go build -tags ocr .

OCR_ENABLED=false also disables text detection.

Development

Run the tests and lint checks:

go test ./... -count=1 -race
go test -tags ocr ./... -count=1 -race
golangci-lint run
golangci-lint run --build-tags ocr
PARITY_REQUIRE=1 go test ./engine -run TestParity

The OCR tests require Tesseract. The parity tests require the models and ONNX Runtime. CI also runs go vet, govulncheck, and a Docker smoke test. Release jobs require successful CI checks before they publish images. The lint configuration adapts the Golden config.

Model tools: manifest · download · export · parity fixtures · benchmark. Stub generation uses make proto.

Models and licenses

The code uses AGPL-3.0. Model licenses apply separately.

Review the model licenses before commercial use. The compat model has non-commercial and no-derivatives restrictions. Review its license before you export or redistribute it.

Runtime: onnxruntime_go. OCR: gosseract and Tesseract.

Support

If this project helps you, you can support its development.

Support me on Ko-fi Buy me a coffee

If this project helps you, consider giving it a star. Bug reports and contributions are welcome.

content-moderation
docker
free-software
golang
grpc
image-classification
image-moderation
machine-learning
nsfw-classifier
nsfw-recognition
ocr
onnx
onnxruntime
open-source
rest-api
self-hosted
selfhosting
tesseract

M1chlCZ/nsfw_sherlock

Free, self-hosted image moderation API in Go. Check NSFW images on your own server with HTTP, gRPC, Docker, and optional OCR. No subscription or per-image API fees.

Go

29

127 commits

updated Oct 14, 2026

See the code

README

NSFW Sherlock logo: a magnifying glass over an image

NSFW Sherlock

Free, self-hosted image moderation.
Run it on your server. Keep image analysis local.

License: AGPL Docker Hub

NSFW Sherlock is a free, open-source API that checks images for NSFW content on your own hardware. It has no subscription or per-image API fees. You cover your own hardware and hosting costs.

  • Self-hosted: Image analysis runs on your server, without an external moderation API.
  • Easy to connect: Use HTTP or gRPC from your application.
  • Image checks: Classify photos and anime, and detect explicit regions.
  • Optional OCR: Use Tesseract to detect words in images.
  • Docker: Start with one command on Linux amd64 or arm64.

One Go binary runs the models with ONNX Runtime. The code uses AGPL-3.0. Model licenses apply separately.

Run with Docker

Run the CPU image:

docker run -e APP_ENV=web -p 4000:4000 m1chl/nsfw-sherlock

Make sure that the service responds:

curl http://localhost:4000/ping

The image includes the models and OCR support. It supports Linux amd64 and arm64. Docker Hub and GHCR publish the same images.

For gRPC, set APP_ENV=grpc. The default interface is HTTP.

Run a release binary

The releases page has archives for Linux amd64, Linux arm64, and macOS arm64, with checksums. The binaries do not include OCR support.

Clone the repository and unpack the archive into it. Then download the models and the runtime:

scripts/fetch-models.sh --ort-only
scripts/fetch-models.sh
./nsfw-sherlock

API

All image endpoints accept this JSON request:

{"base64":"<base64-encoded image>","filename":"image.jpg"}
HTTP endpointResponse
GET /pingService status
POST /pic/checknsfwPic and nsfwText flags
POST /pic/labelsProbabilities for drawings, hentai, neutral, porn, and sexy
POST /pic/analyzeFull analysis, model scores, region detections, and elapsed time

Example response from /pic/check:

{"status":"ok","message":"success","nsfwText":false,"nsfwPic":false}

The full analysis includes a verdict (sfw, suggestive, or explicit) and an nsfw score. Errors use {"errorMessage":"...","status":"FAIL","hasError":true}.

The gRPC service exposes Detect, DetectLabels, and Analyze. The service definition contains the request and response types.

GPU support

NVIDIA · CUDA

Install an NVIDIA driver compatible with CUDA 12.9 and the NVIDIA Container Toolkit. Then run the CUDA image:

docker run --gpus all -p 4000:4000 m1chl/nsfw-sherlock:v1.0.5-cuda

This image supports Linux amd64. It includes ONNX Runtime 1.29.0, CUDA 12, and cuDNN. ORT_DEVICE_ID selects the GPU index, with 0 as the default.

AMD · ROCm / MIGraphX

Install ROCm and a MIGraphX-enabled ONNX Runtime 1.29.0 shared library. Set ORT_PROVIDER=rocm. Point ORT_LIB to that library. Keep the provider libraries beside it. Add the ROCm dependencies to the library search path.

The rocm value is an alias for migraphx. The Go binding requires ORT API 29. Older runtimes are incompatible. This project does not publish an AMD image. The MIGraphX guide describes the runtime build.

If the selected provider is unavailable, the service stops at startup. Unsupported operators can still use the CPU. GPU inference remains untested on physical NVIDIA or AMD hardware.

Configuration

VariableDefaultPurpose
APP_ENVwebHTTP (web) or gRPC (grpc). http is a deprecated alias.
PORT4000Service port
NSFW_PROFILEbalancedModel profile
ORT_PROVIDERcpucpu, cuda, or migraphx. rocm aliases migraphx.
ORT_DEVICE_ID0GPU index
OCR_ENABLEDtrueText detection. Requires a build with OCR support.
Paths, limits, and logging
VariableDefaultPurpose
MODELS_DIR./assets/modelsModel directory
MANIFESTmodels/manifest.jsonModel manifest
ORT_LIBAuto-detectedONNX Runtime shared library path
BAD_WORDS_FILEAuto-detectedOCR word list. Uses an embedded list as a fallback.
MAX_IMAGE_BYTES20971520 (20 MiB)Maximum image size
MAX_IMAGE_PIXELS50000000Maximum decoded pixel count
SESSION_POOL_SIZE2Sessions per model
NSFW_ALLOW_DEGRADEDfalseAllow startup after a required model fails to load.
LOG_LEVELinfodebug, info, warn, or error
LOG_FORMATtexttext or json

Docker images supply the model and runtime paths. They use JSON logs.

Model profiles

ProfilePhoto modelAnime modelRegion detector
balanced (default)Freepik EVA02CaFormerNudeNet 320px
maxFreepik EVA02CaFormerNudeNet 640px
fastFreepik EVA02MobileNetV3NudeNet 320px
compatViT5 with five legacy labelsNoneNone

Build from source

Requirements: Go 1.27, a C compiler, Python 3, and curl. The runtime download supports Linux amd64, Linux arm64, and macOS arm64.

Download the source, runtime, and models. Then build the binary. Run the binary:

git clone https://github.com/M1chlCZ/nsfw_sherlock
cd nsfw_sherlock
scripts/fetch-models.sh --ort-only
scripts/fetch-models.sh
go build .
./nsfw_sherlock

The download script uses pinned SHA-256 digests for the runtime and models. The engine also compares each model digest with the manifest at startup. This source build excludes OCR and always reports nsfwText: false.

For OCR support, install Tesseract, Leptonica, their development libraries, and the English language data. Then build with the OCR tag:

go build -tags ocr .

OCR_ENABLED=false also disables text detection.

Development

Run the tests and lint checks:

go test ./... -count=1 -race
go test -tags ocr ./... -count=1 -race
golangci-lint run
golangci-lint run --build-tags ocr
PARITY_REQUIRE=1 go test ./engine -run TestParity

The OCR tests require Tesseract. The parity tests require the models and ONNX Runtime. CI also runs go vet, govulncheck, and a Docker smoke test. Release jobs require successful CI checks before they publish images. The lint configuration adapts the Golden config.

Model tools: manifest · download · export · parity fixtures · benchmark. Stub generation uses make proto.

Models and licenses

The code uses AGPL-3.0. Model licenses apply separately.

Review the model licenses before commercial use. The compat model has non-commercial and no-derivatives restrictions. Review its license before you export or redistribute it.

Runtime: onnxruntime_go. OCR: gosseract and Tesseract.

Support

If this project helps you, you can support its development.

Support me on Ko-fi Buy me a coffee

If this project helps you, consider giving it a star. Bug reports and contributions are welcome.

content-moderation
docker
free-software
golang
grpc
image-classification
image-moderation
machine-learning
nsfw-classifier
nsfw-recognition
ocr
onnx
onnxruntime
open-source
rest-api
self-hosted
selfhosting
tesseract