### Bundle Application and Start Dockerized Nginx
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/manual_testing/README.md
Run these commands to bundle the application and start a local Nginx server. This setup is used to avoid CORS issues during manual testing.
```sh
yarn bundle
```
```sh
docker-compose up -d
```
```sh
http://localhost/data/index.html
```
--------------------------------
### Build and Run Node.js NSFWJS Demo
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/node_demo/README.md
Commands to build the project, install dependencies for the Node.js demo, and start the Express server.
```bash
yarn build
yarn --cwd examples/node_demo install
yarn --cwd examples/node_demo start
```
--------------------------------
### Install NSFWJS and TensorFlow.js
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Install the necessary peer dependency and the NSFWJS library using yarn or npm.
```bash
# Install peer dependency
yarn add @tensorflow/tfjs
# Install NSFWJS
yarn add nsfwjs
```
```bash
# For Node.js (better performance)
npm install nsfwjs @tensorflow/tfjs-node
```
--------------------------------
### Install WebGPU Backend for TensorFlow.js
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Installs the WebGPU backend for TensorFlow.js, which often provides the fastest performance on supported browsers and hardware.
```bash
yarn add @tensorflow/tfjs-backend-webgpu
```
--------------------------------
### Install NSFWJS and TensorFlow.js Node
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Install the NSFWJS library and the TensorFlow.js Node.js backend using npm for server-side applications.
```bash
$ npm install nsfwjs
$ npm install @tensorflow/tfjs-node
```
--------------------------------
### Install WASM Backend for TensorFlow.js
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Installs the WASM backend for TensorFlow.js. This is useful as a fallback when WebGL is unavailable or restricted.
```bash
yarn add @tensorflow/tfjs-backend-wasm
```
--------------------------------
### Load Default NSFWJS Model
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads the default NSFWJS model. This is the simplest way to get started.
```javascript
const model = nsfwjs.load(); // Default: "MobileNetV2"
```
--------------------------------
### Install NSFWJS and TensorFlow.js Peer Dependency
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Installs NSFWJS and its peer dependency, TensorFlow.js, using yarn. Add TensorFlow.js if your project doesn't already include it.
```bash
# peer dependency
$ yarn add @tensorflow/tfjs
# install NSFWJS
$ yarn add nsfwjs
```
--------------------------------
### Send Image to NSFWJS API
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/node_demo/README.md
Example using curl to send an image file via multipart/form-data to the Node.js NSFWJS server's /nsfw endpoint for classification.
```bash
curl -X POST http://localhost:8080/nsfw \
-F "image=@/path/to/image.jpg"
```
--------------------------------
### Core entrypoint with selective model bundling (`nsfwjs/core`)
Source: https://context7.com/infinitered/nsfwjs/llms.txt
The `nsfwjs/core` entrypoint omits all built-in model definitions by default, enabling tree-shaking. Pass only the models needed via `modelDefinitions`.
```APIDOC
## load — Core entrypoint with selective model bundling (`nsfwjs/core`)
The `nsfwjs/core` entrypoint omits all built-in model definitions by default, enabling tree-shaking. Pass only the models needed via `modelDefinitions`.
### Usage
```js
import { load } from "nsfwjs/core";
import { MobileNetV2Model } from "nsfwjs/models/mobilenet_v2";
import { MobileNetV2MidModel } from "nsfwjs/models/mobilenet_v2_mid";
import { InceptionV3Model } from "nsfwjs/models/inception_v3";
// Only MobileNetV2 is bundled into the app
const model = await load("MobileNetV2", {
modelDefinitions: [MobileNetV2Model],
});
// Multiple models available to select from
const multiModel = await load("MobileNetV2Mid", {
modelDefinitions: [MobileNetV2Model, MobileNetV2MidModel],
type: "graph",
});
// Throws — named model not in registry
try {
await load("MobileNetV2", { modelDefinitions: [] }); // Error: provided models registry
} catch (err) {
console.error(err.message);
}
// Load from URL via core — no bundled models pulled into bundle
const hostedModel = await load("https://cdn.example.com/models/mobilenet_v2/", {
modelDefinitions: [], // empty ok when using URL
});
```
```
--------------------------------
### Load Model with Core Entrypoint (Selective Bundling)
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Use the `nsfwjs/core` entrypoint to omit built-in models by default, enabling tree-shaking. Pass only the required models via `modelDefinitions`. Handles loading from URLs without bundling models.
```javascript
import { load } from "nsfwjs/core";
import { MobileNetV2Model } from "nsfwjs/models/mobilenet_v2";
import { MobileNetV2MidModel } from "nsfwjs/models/mobilenet_v2_mid";
import { InceptionV3Model } from "nsfwjs/models/inception_v3";
// Only MobileNetV2 is bundled into the app
const model = await load("MobileNetV2", {
modelDefinitions: [MobileNetV2Model],
});
// Multiple models available to select from
const multiModel = await load("MobileNetV2Mid", {
modelDefinitions: [MobileNetV2Model, MobileNetV2MidModel],
type: "graph",
});
// Throws — named model not in registry
try {
await load("MobileNetV2", { modelDefinitions: [] }); // Error: provided models registry
} catch (err) {
console.error(err.message);
}
// Load from URL via core — no bundled models pulled into bundle
const hostedModel = await load("https://cdn.example.com/models/mobilenet_v2/", {
modelDefinitions: [], // empty ok when using URL
});
```
--------------------------------
### Load a model (default entrypoint)
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Loads one of the three bundled models by name, or falls back to `MobileNetV2` when called with no arguments. All bundled model definitions are included automatically.
```APIDOC
## load — Load a model (default entrypoint)
Loads one of the three bundled models by name, or falls back to `MobileNetV2` when called with no arguments. All bundled model definitions are included automatically.
### Usage
```js
import * as nsfwjs from "nsfwjs";
// Default: MobileNetV2 (224×224 layers model)
const model = await nsfwjs.load();
// Explicit named model — "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
const midModel = await nsfwjs.load("MobileNetV2Mid");
const inceptModel = await nsfwjs.load("InceptionV3");
// Load from a self-hosted URL (reduces bundle size — binary weights instead of base64)
const hosted = await nsfwjs.load("https://yoursite.com/models/mobilenet_v2/");
// Load from IndexedDB cache (browser)
const cached = await nsfwjs.load("indexeddb://myModel");
// Load MobileNetV2Mid from URL — graph model requires { type: 'graph' }
const graphModel = await nsfwjs.load("/models/mobilenet_v2_mid/", { type: "graph" });
// InceptionV3 requires size: 299
const v3 = await nsfwjs.load("/models/inception_v3/", { size: 299 });
```
```
--------------------------------
### Load a Model with NSFWJS (Default Entrypoint)
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Load one of the three bundled models by name. Falls back to 'MobileNetV2' if no argument is provided. Supports loading from URLs, IndexedDB, or with specific configurations for graph models and image sizes.
```javascript
import * as nsfwjs from "nsfwjs";
// Default: MobileNetV2 (224×224 layers model)
const model = await nsfwjs.load();
// Explicit named model — "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
const midModel = await nsfwjs.load("MobileNetV2Mid");
const inceptModel = await nsfwjs.load("InceptionV3");
// Load from a self-hosted URL (reduces bundle size — binary weights instead of base64)
const hosted = await nsfwjs.load("https://yoursite.com/models/mobilenet_v2/");
// Load from IndexedDB cache (browser)
const cached = await nsfwjs.load("indexeddb://myModel");
// Load MobileNetV2Mid from URL — graph model requires { type: 'graph' }
const graphModel = await nsfwjs.load("/models/mobilenet_v2_mid/", { type: "graph" });
// InceptionV3 requires size: 299
const v3 = await nsfwjs.load("/models/inception_v3/", { size: 299 });
```
--------------------------------
### TensorFlow.js Backend Selection for NSFWJS
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Demonstrates how to configure TensorFlow.js backends before loading the NSFWJS model. It covers automatic best-backend selection, explicit WebGPU, and WASM fallback, along with enabling production mode.
```javascript
import * as tf from "@tensorflow/tfjs";
import "@tensorflow/tfjs-backend-webgpu";
import "@tensorflow/tfjs-backend-wasm";
import { setWasmPaths } from "@tensorflow/tfjs-backend-wasm";
import * as nsfwjs from "nsfwjs";
// Automatic best-backend selection (recommended)
await tf.ready();
const model = await nsfwjs.load();
// Explicit WebGPU (fastest on supported hardware)
await tf.setBackend("webgpu");
await tf.ready();
// WASM fallback (for environments without WebGL)
setWasmPaths("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm/dist/");
await tf.setBackend("wasm");
await tf.ready();
// Production: enable prod mode before loading model
tf.enableProdMode();
const prodModel = await nsfwjs.load("https://yoursite.com/models/mobilenet_v2/");
```
--------------------------------
### Load NSFWJS in Browser with Script Tags
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Load NSFWJS in a browser without a bundler using pre-built script tags. Ensure TensorFlow.js is loaded first.
```html
```
--------------------------------
### Load NSFWJS Model from Directory
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads a model from a specified directory path. Ensure the directory contains `model.json` and associated files.
```javascript
const model = nsfwjs.load("/path/to/mobilenet_v2/");
```
--------------------------------
### Configure and Set WASM Backend for TensorFlow.js
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Configures the path to WASM binaries and sets the TensorFlow.js backend to 'wasm'. Useful for environments without standard bundlers.
```javascript
import * as tf from "@tensorflow/tfjs";
import {
setWasmPaths,
} from "@tensorflow/tfjs-backend-wasm";
import "@tensorflow/tfjs-backend-wasm";
// If you aren't using a standard bundler, set the path to the .wasm binaries.
setWasmPaths("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm/dist/");
await tf.setBackend("wasm");
await tf.ready();
```
--------------------------------
### Selective Model Loading with NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Import specific models for tree-shaking and pass them to the load function. Loading with an empty model registry will cause an error.
```javascript
import { load } from "nsfwjs/core";
import { MobileNetV2Model } from "nsfwjs/models/mobilenet_v2";
import { MobileNetV2MidModel } from "nsfwjs/models/mobilenet_v2_mid";
const model = await load("MobileNetV2", {
modelDefinitions: [MobileNetV2Model, MobileNetV2MidModel],
});
```
```javascript
await load("MobileNetV2", { modelDefinitions: [] }); // throws
```
--------------------------------
### Selective Model Bundles
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Demonstrates how to selectively import and load specific model bundles for tree-shaking purposes.
```APIDOC
## load with modelDefinitions
### Description
Loads a specific model by providing model definitions, allowing for selective bundling and tree-shaking.
### Method
`nsfwjs.load(modelName, { modelDefinitions: [...] })`
### Parameters
- **modelName** (string) - The name of the model to load (e.g., "MobileNetV2").
- **modelDefinitions** (array) - An array of model definitions to include. If empty, named bundled model loads will fail.
### Request Example
```javascript
import { load } from "nsfwjs/core";
import { MobileNetV2Model } from "nsfwjs/models/mobilenet_v2";
import { MobileNetV2MidModel } from "nsfwjs/models/mobilenet_v2_mid";
const model = await load("MobileNetV2", {
modelDefinitions: [MobileNetV2Model, MobileNetV2MidModel],
});
// Example of failure with empty modelDefinitions
// await load("MobileNetV2", { modelDefinitions: [] }); // throws
```
### Response
- **model** (object) - The loaded NSFWJS model object.
```
--------------------------------
### Automatic Backend Selection with TensorFlow.js
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Allows TensorFlow.js to automatically select the best available backend. Ensure necessary backends are imported and `tf.ready()` is called.
```javascript
import * as tf from "@tensorflow/tfjs";
import "@tensorflow/tfjs-backend-webgpu";
import "@tensorflow/tfjs-backend-wasm";
import * as nsfwjs from "nsfwjs";
await tf.ready();
const model = await nsfwjs.load();
```
--------------------------------
### Pinned Backend Selection with TensorFlow.js
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Explicitly sets the TensorFlow.js backend to 'webgpu' for deterministic behavior. Ensure the backend is imported and `tf.ready()` is called.
```javascript
import * as tf from "@tensorflow/tfjs";
import "@tensorflow/tfjs-backend-webgpu";
await tf.setBackend("webgpu");
await tf.ready();
```
--------------------------------
### model.classify (Node.js)
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Demonstrates how to use the `model.classify` method in a Node.js environment using `@tensorflow/tfjs-node`. It shows how to read an image file, decode it into a tensor, perform classification, and manage tensor memory.
```APIDOC
## `model.classify` — Node.js usage
Use `@tensorflow/tfjs-node` for server-side classification. Decode images into `tf.Tensor3D` with `tf.node.decodeImage`.
```js
const tf = require("@tensorflow/tfjs-node");
const nsfw = require("nsfwjs");
const fs = require("fs");
async function classifyFile(filePath) {
const model = await nsfw.load();
const imageBuffer = fs.readFileSync(filePath);
// decodeImage returns Tensor3D for 3-channel images
const image = tf.node.decodeImage(imageBuffer, 3);
try {
const predictions = await model.classify(image);
console.log("Predictions:", predictions);
// [
// { className: "Neutral", probability: 0.87 },
// ...
// ]
return predictions;
} finally {
image.dispose(); // Must dispose tensors manually
model.dispose();
}
}
classifyFile("./photo.jpg");
```
```
--------------------------------
### Load Model with Custom Size Option
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads a model and specifies its expected input size using the `size` option. This is useful for models with dimensions other than the default 224x224.
```javascript
const model = nsfwjs.load("/path/to/inception_v3/", { size: 299 });
```
--------------------------------
### Include NSFWJS in Browser with Script Tags
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Include the necessary NSFWJS model files and the main bundle using script tags in your HTML. Ensure all files are hosted alongside your project.
```html
```
--------------------------------
### Enable Production Mode for NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Enable production mode before loading the NSFWJS model for performance in production environments. Ensure TensorFlow.js is imported.
```javascript
import * as tf from "@tensorflow/tfjs";
import * as nsfwjs from "nsfwjs";
tf.enableProdMode();
//...
let model = await nsfwjs.load(`${urlToNSFWJSModel}`);
```
--------------------------------
### Load NSFWJS Model from Custom URL (Core)
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Imports `load` from `nsfwjs/core` to load a model from a custom URL. This is recommended for smaller app bundles as it avoids including built-in model definitions.
```javascript
import { load } from "nsfwjs/core";
const model = await load("/path/to/mobilenet_v2/model.json");
```
--------------------------------
### Classify Image with NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/minimal_demo/index.html
Load the NSFWJS model and classify an image. Ensure the image is loaded before classification. Predictions are logged to the console.
```javascript
// const nsfwjs = require('nsfwjs')
const img = new Image();
img.crossOrigin = "anonymous";
// some image here
img.src = "https://i.imgur.com/Kwxetau.jpg";
img.onload = function () {
// Load the model.
nsfwjs.load("MobileNetV2Mid").then((model) => {
// Classify the image.
model.classify(img).then((predictions) => {
console.log("Predictions", predictions);
});
});
};
```
--------------------------------
### Enable Type-Aware ESLint Rules
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/nsfw_demo/README.md
Configure ESLint to use type-aware lint rules by extending recommendedTypeChecked, strictTypeChecked, or stylisticTypeChecked configurations. Ensure project configurations are correctly specified in parserOptions.
```javascript
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
]);
```
--------------------------------
### Load Graph Model with Options
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads a graph-type model and specifies the model type in the options. Graph models require this explicit type declaration.
```javascript
/* You may need to load this model with graph type */
const model = nsfwjs.load("/path/to/mobilenet_v2_mid/", { type: 'graph' });
```
--------------------------------
### Create NSFW Image Upload Endpoint with Express
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Set up an Express.js server to handle multipart/form-data image uploads and classify them using NSFWJS. The model is loaded once to optimize performance.
```javascript
const express = require("express");
const multer = require("multer");
const jpeg = require("jpeg-js");
const tf = require("@tensorflow/tfjs-node");
const nsfw = require("nsfwjs");
const app = express();
const upload = multer();
let _model;
const convert = async (img) => {
// Decoded image in UInt8 Byte array
const image = await jpeg.decode(img, { useTArray: true });
const numChannels = 3;
const numPixels = image.width * image.height;
const values = new Int32Array(numPixels * numChannels);
for (let i = 0; i < numPixels; i++)
for (let c = 0; c < numChannels; ++c)
values[i * numChannels + c] = image.data[i * 4 + c];
return tf.tensor3d(values, [image.height, image.width, numChannels], "int32");
};
app.post("/nsfw", upload.single("image"), async (req, res) => {
if (!req.file) res.status(400).send("Missing image multipart/form-data");
else {
const image = await convert(req.file.buffer);
const predictions = await _model.classify(image);
image.dispose();
res.json(predictions);
}
});
const load_model = async () => {
_model = await nsfw.load();
};
// Keep the model in memory, make sure it's loaded only once
load_model().then(() => app.listen(8080));
// curl --request POST localhost:8080/nsfw --header 'Content-Type: multipart/form-data' --data-binary 'image=@/full/path/to/picture.jpg'
```
--------------------------------
### Load Model
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads the NSFWJS model. You can optionally specify a model to host on your own or use a different model from the ones available.
```APIDOC
## load
### Description
Loads the NSFWJS model. This function is asynchronous and returns a Promise that resolves with the loaded model.
### Method
`nsfwjs.load()`
### Parameters
None
### Request Example
```javascript
import * as nsfwjs from "nsfwjs";
const model = await nsfwjs.load();
```
### Response
- **model** (object) - The loaded NSFWJS model object, which has a `classify` method.
```
--------------------------------
### Load and Classify Image with NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Basic usage of NSFWJS to load a model and classify an image. Ensure the image element exists in the DOM.
```javascript
import * as nsfwjs from "nsfwjs";
const img = document.getElementById("img");
// If you want to host models on your own or use different model from the ones available, see the section "Host your own model".
const model = await nsfwjs.load();
// Classify the image
const predictions = await model.classify(img);
console.log("Predictions: ", predictions);
```
--------------------------------
### Load Model
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads the NSFWJS model. It can load default models, specific bundled models, or custom models from a provided URL or path. Options for model type and size can be specified.
```APIDOC
## `load` the model
Before you can classify any image, you'll need to load the model.
```js
const model = nsfwjs.load(); // Default: "MobileNetV2"
```
You can use the optional first parameter to specify which model you want to use from the three built-in bundled models. Defaults to: `"MobileNetV2"`.
```js
const model = nsfwjs.load("MobileNetV2Mid"); // "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
```
If you are hosting your own model via URL and want the smallest app bundle, import `load` from `nsfwjs/core` instead of `nsfwjs`.
```js
import { load } from "nsfwjs/core";
const model = await load("/path/to/mobilenet_v2/model.json");
```
```js
const model = nsfwjs.load("/path/to/mobilenet_v2/");
```
If you're using a model that needs an image of dimension other than 224x224, you can pass the size in the options parameter.
```js
/* You may need to load this model with graph type */
const model = nsfwjs.load("/path/to/mobilenet_v2_mid/", { type: 'graph' });
```
```js
const model = nsfwjs.load("/path/to/inception_v3/", { size: 299 });
```
### Parameters
Initial Load:
1. URL or path to folder containing `model.json`.
2. Optional object with size or type property that your model expects.
Subsequent Load:
1. IndexedDB path.
2. Optional object with size or type property that your model expects.
**Returns**
- Ready to use NSFWJS model object
```
--------------------------------
### Load Specific NSFWJS Model
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Loads a specific NSFWJS model by name. Use this to choose between 'MobileNetV2', 'MobileNetV2Mid', or 'InceptionV3'.
```javascript
const model = nsfwjs.load("MobileNetV2Mid"); // "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
```
--------------------------------
### Classify Images with NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/manual_testing/data/index.html
Loads the NSFWJS model and classifies all images on the page. Use this to test model accuracy on different image formats.
```javascript
nsfwjs.load("MobileNetV2Mid").then(model => {
const images = document.querySelectorAll('img')
for (let i = 0; i < images.length; i++) {
model.classify(images[i], 3)
.then(predictions => showResults(images[i], predictions, true))
.catch(error => showError(images[i], error))
}
})
```
--------------------------------
### Model Caching with IndexedDB in Browser
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Saves a model to IndexedDB on first load to avoid re-downloading on subsequent page loads. Handles cache misses by loading from a hosted URL and persisting the model.
```javascript
import * as nsfwjs from "nsfwjs";
const MODEL_KEY = "indexeddb://nsfwjs-mobilenet-v2";
async function getModel() {
let model;
try {
// Attempt to load from IndexedDB cache
model = await nsfwjs.load(MODEL_KEY);
console.log("Loaded from IndexedDB cache");
} catch {
// Cache miss — load from hosted URL and persist
model = await nsfwjs.load("https://yoursite.com/models/mobilenet_v2/");
await model.model.save(MODEL_KEY);
console.log("Model saved to IndexedDB");
}
return model;
}
const model = await getModel();
const img = document.getElementById("photo");
const predictions = await model.classify(img);
console.log(predictions);
```
--------------------------------
### Web Worker with IndexedDB Caching for Production
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Offloads model loading and inference to a Web Worker to keep the main thread responsive. It attempts to load from IndexedDB first and falls back to a bundled model if the cache is missed.
```typescript
// nsfwjs.worker.ts
import { load } from "nsfwjs/core";
import { MobileNetV2Model, MobileNetV2MidModel, InceptionV3Model } from "nsfwjs/models/mobilenet_v2";
import type { ModelName, NSFWJS, PredictionType } from "nsfwjs";
let model: NSFWJS | null = null;
onmessage = async (event: MessageEvent<{ type: string; modelName?: ModelName; file?: File }>) => {
const { type, modelName, file } = event.data;
if (type === "load" && modelName) {
try {
// Try IndexedDB first, fall back to bundled model
try {
model = await load(`indexeddb://${modelName}`, {});
} catch {
model = await load(modelName, {
modelDefinitions: [MobileNetV2Model, MobileNetV2MidModel, InceptionV3Model],
});
await model.model.save(`indexeddb://${modelName}`);
}
postMessage({ modelLoaded: true });
} catch (err) {
postMessage({ error: err instanceof Error ? err.message : "Failed" });
}
}
if (type === "predict" && file && model) {
const bitmap = await createImageBitmap(file);
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
const ctx = canvas.getContext("2d")!;
ctx.drawImage(bitmap, 0, 0);
const imageData = ctx.getImageData(0, 0, bitmap.width, bitmap.height);
const predictions: PredictionType[] = await model.classify(imageData);
bitmap.close();
postMessage({ predictions });
}
};
// main.ts — usage
const worker = new Worker(new URL("./nsfwjs.worker.ts", import.meta.url), { type: "module" });
worker.postMessage({ type: "load", modelName: "MobileNetV2" });
worker.onmessage = (e) => {
if (e.data.modelLoaded) {
const fileInput = document.querySelector("#fileInput")!;
worker.postMessage({ type: "predict", file: fileInput.files![0] });
}
if (e.data.predictions) {
console.log("Predictions:", e.data.predictions);
}
};
```
--------------------------------
### Classify Image in Node.js with NSFWJS
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Use NSFWJS in a Node.js application to classify an image fetched via HTTP. Ensure to manage tensor memory by disposing of images after use.
```javascript
const axios = require("axios"); //you can use any http client
const tf = require("@tensorflow/tfjs-node");
const nsfw = require("nsfwjs");
async function fn() {
const pic = await axios.get(`link-to-picture`, {
responseType: "arraybuffer",
});
const model = await nsfw.load(); // To load a local model, nsfw.load('file://./path/to/model/')
// Image must be in tf.tensor3d format
// you can convert image to tf.tensor3d with tf.node.decodeImage(Uint8Array,channels)
const image = await tf.node.decodeImage(pic.data, 3);
const predictions = await model.classify(image);
image.dispose(); // Tensor memory must be managed explicitly (it is not sufficient to let a tf.Tensor go out of scope for its memory to be released).
console.log(predictions);
}
fn();
```
--------------------------------
### Add React-Specific ESLint Rules
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/nsfw_demo/README.md
Integrate eslint-plugin-react-x and eslint-plugin-react-dom to enable lint rules specifically for React and React DOM development. This enhances code quality and adherence to React best practices.
```javascript
// eslint.config.js
import reactX from "eslint-plugin-react-x";
import reactDom from "eslint-plugin-react-dom";
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs["recommended-typescript"],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
]);
```
--------------------------------
### Classify Image in Node.js with tfjs-node
Source: https://github.com/infinitered/nsfwjs/wiki/FAQ:-NSFW-JS
Use this snippet to classify images in a Node.js environment with tfjs-node. Ensure the model is loaded from a local path and image preprocessing is handled correctly.
```javascript
const tf =require('@tensorflow/tfjs-node')
const load=require('./dist/index').load
const fs = require('fs');
const jpeg = require('jpeg-js');
// Fix for JEST
const globalAny = global
globalAny.fetch = require('node-fetch')
const timeoutMS = 10000
const NUMBER_OF_CHANNELS = 3
const readImage = (path) => {
const buf = fs.readFileSync(path)
const pixels = jpeg.decode(buf, true)
return pixels
}
const imageByteArray = (image, numChannels) => {
const pixels = image.data
const numPixels = image.width * image.height;
const values = new Int32Array(numPixels * numChannels);
for (let i = 0; i < numPixels; i++) {
for (let channel = 0; channel < numChannels; ++channel) {
values[i * numChannels + channel] = pixels[i * 4 + channel];
}
}
return values
}
const imageToInput = (image, numChannels) => {
const values = imageByteArray(image, numChannels)
const outShape = [image.height, image.width, numChannels] ;
const input = tf.tensor3d(values, outShape, 'int32');
return input
}
(async()=>{
const model = await load('file://./model/')//moved model at root of folder
const logo = readImage(`./_art/nsfwjs_logo.jpg`)
const input = imageToInput(logo, NUMBER_OF_CHANNELS)
console.time('predict')
const predictions = await model.classify(input)
console.timeEnd('predict')
console.log(predictions)
})()
```
--------------------------------
### Cache and Load Model from IndexedDB
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Saves a loaded model to IndexedDB for faster subsequent loads and then loads it from there. This is beneficial for browser-based applications.
```javascript
const initialLoad = await nsfwjs.load(
"/path/to/different/model/" /*, { ...options }*/
);
await initialLoad.model.save("indexeddb://exampleModel");
const model = await nsfwjs.load("indexeddb://exampleModel" /*, { ...options }*/);
```
--------------------------------
### Express.js REST API for Image Classification
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Builds a multipart/form-data endpoint using Express.js and Multer to classify uploaded images server-side. The model is loaded once at startup and kept in memory for efficiency.
```javascript
const tf = require("@tensorflow/tfjs-node");
const express = require("express");
const multer = require("multer");
const nsfw = require("nsfwjs");
const app = express();
const upload = multer();
let model;
app.post("/nsfw", upload.single("image"), async (req, res) => {
if (!req.file) {
return res.status(400).json({ error: "Missing image in multipart/form-data" });
}
const image = tf.node.decodeImage(req.file.buffer, 3);
try {
const predictions = await model.classify(image);
res.json(predictions);
// [
// { className: "Neutral", probability: 0.91 },
// { className: "Drawing", probability: 0.05 },
// ...
// ]
} catch (err) {
res.status(500).json({ error: err.message });
} finally {
image.dispose();
}
});
// Load model once at startup, keep in memory
nsfw.load().then((m) => {
model = m;
app.listen(8080, () => console.log("Server running on :8080"));
});
// Test with curl:
// curl --request POST localhost:8080/nsfw \
// --header 'Content-Type: multipart/form-data' \
// --form 'image=@/path/to/image.jpg'
```
--------------------------------
### model.classify
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Classifies an image using a pre-loaded NSFWJS model. It accepts various image input types and returns an array of prediction objects, each containing a class name and its probability. You can also specify the number of top results to return.
```APIDOC
## `model.classify` — Classify an image
Accepts a DOM image element, video element, canvas, `ImageData`, or a `tf.Tensor3D`. Returns an array of `{ className, probability }` objects sorted by probability descending.
```js
import * as nsfwjs from "nsfwjs";
const model = await nsfwjs.load();
// Classify from an
element — returns all 5 classes
const img = document.getElementById("myImage"); // HTMLImageElement
const predictions = await model.classify(img);
console.log(predictions);
// [
// { className: "Neutral", probability: 0.912 },
// { className: "Drawing", probability: 0.051 },
// { className: "Sexy", probability: 0.023 },
// { className: "Porn", probability: 0.009 },
// { className: "Hentai", probability: 0.005 },
// ]
// Return only top 3 results
const top3 = await model.classify(img, 3);
// Classify from a video element (current frame)
const video = document.getElementById("myVideo"); // HTMLVideoElement
const videoPredictions = await model.classify(video);
// Classify from a canvas element
const canvas = document.getElementById("myCanvas"); // HTMLCanvasElement
const canvasPredictions = await model.classify(canvas);
// Classify from a tf.Tensor3D (manage tensor memory manually)
import * as tf from "@tensorflow/tfjs";
const tensor = tf.zeros([224, 224, 3]) as tf.Tensor3D;
try {
const tensorPredictions = await model.classify(tensor);
console.log(tensorPredictions);
} finally {
tensor.dispose();
}
// Simple safe/unsafe check
const isNSFW = predictions[0].className !== "Neutral" &&
predictions[0].className !== "Drawing" &&
predictions[0].probability > 0.7;
```
```
--------------------------------
### Release Model Resources
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Dispose of the NSFWJS model to free up memory. This operation is idempotent and subsequent calls to classify or infer will throw an error. Recommended for one-shot classification.
```javascript
import * as nsfwjs from "nsfwjs";
const model = await nsfwjs.load();
const img = document.getElementById("myImage");
const predictions = await model.classify(img);
console.log(predictions);
// Release all GPU/CPU memory used by the model
model.dispose();
// Subsequent calls throw "This NSFWJS instance has been disposed."
try {
await model.classify(img);
} catch (err) {
console.error(err.message); // "This NSFWJS instance has been disposed."
}
// Pattern: one-shot classification
async function classifyOnce(imgElement) {
const m = await nsfwjs.load();
try {
return await m.classify(imgElement);
} finally {
m.dispose();
}
}
```
--------------------------------
### Classify Image with Custom Prediction Count
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Classifies an image using the loaded model and returns a specified number of top predictions. By default, it returns all 5 predictions.
```javascript
// Return top 3 guesses (instead of all 5)
const predictions = await model.classify(img, 3);
```
--------------------------------
### Display Classification Results
Source: https://github.com/infinitered/nsfwjs/blob/master/examples/manual_testing/data/index.html
Helper function to display classification results for a single media element. Appends the results as a paragraph below the image.
```javascript
function showResults(mediaElement, predictions, isSingle = false) {
if (isSingle) {
const html = predictions.map(({className, probability}) => `${className}: ${Math.round(probability * 10000) / 10000} `).join('')
const el = document.createElement('p')
el.style.cssText = 'font-size:13px;'
el.innerHTML = html
mediaElement.parentElement.append(el)
} else {
for (let j = 0; j < predictions.length; j++) {
const html = predictions[j].map(({className, probability}) => `${className}: ${Math.round(probability * 10000) / 10000} `).join('')
const el = document.createElement('p')
el.style.cssText = 'font-size:13px;'
el.innerHTML = html
mediaElement.parentElement.append(el)
}
}
}
```
--------------------------------
### Classify Image in Browser
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Classify images from DOM elements or tensors in the browser. Supports specifying the number of top results to return. Ensure tensors are disposed after use.
```javascript
import * as nsfwjs from "nsfwjs";
const model = await nsfwjs.load();
// Classify from an
element — returns all 5 classes
const img = document.getElementById("myImage"); // HTMLImageElement
const predictions = await model.classify(img);
console.log(predictions);
// [
// { className: "Neutral", probability: 0.912 },
// { className: "Drawing", probability: 0.051 },
// { className: "Sexy", probability: 0.023 },
// { className: "Porn", probability: 0.009 },
// { className: "Hentai", probability: 0.005 },
// ]
// Return only top 3 results
const top3 = await model.classify(img, 3);
// Classify from a video element (current frame)
const video = document.getElementById("myVideo"); // HTMLVideoElement
const videoPredictions = await model.classify(video);
// Classify from a canvas element
const canvas = document.getElementById("myCanvas"); // HTMLCanvasElement
const canvasPredictions = await model.classify(canvas);
// Classify from a tf.Tensor3D (manage tensor memory manually)
import * as tf from "@tensorflow/tfjs";
const tensor = tf.zeros([224, 224, 3]) as tf.Tensor3D;
try {
const tensorPredictions = await model.classify(tensor);
console.log(tensorPredictions);
} finally {
tensor.dispose();
}
// Simple safe/unsafe check
const isNSFW = predictions[0].className !== "Neutral" &&
predictions[0].className !== "Drawing" &&
predictions[0].probability > 0.7;
```
--------------------------------
### Classify Image
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Classifies an image using the loaded NSFWJS model. Returns an array of predictions for different NSFW categories.
```APIDOC
## classify
### Description
Classifies an image to determine the probability of it falling into different NSFW categories.
### Method
`model.classify(image)`
### Parameters
- **image** (HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageData | tf.Tensor) - The image to classify.
### Request Example
```javascript
const img = document.getElementById("img");
const predictions = await model.classify(img);
console.log("Predictions: ", predictions);
```
### Response
- **predictions** (array) - An array of objects, where each object represents a prediction for a NSFW category. Each prediction object typically includes:
- **className** (string) - The name of the NSFW class (e.g., 'Drawing', 'Hentai', 'Neutral', 'Porn', 'Sexy').
- **probability** (number) - The probability of the image belonging to this class (0 to 1).
```
--------------------------------
### Classify Image in Node.js
Source: https://context7.com/infinitered/nsfwjs/llms.txt
Perform image classification server-side using Node.js. Requires `@tensorflow/tfjs-node` and `fs` module. Ensure tensors are disposed manually.
```javascript
const tf = require("@tensorflow/tfjs-node");
const nsfw = require("nsfwjs");
const fs = require("fs");
async function classifyFile(filePath) {
const model = await nsfw.load();
const imageBuffer = fs.readFileSync(filePath);
// decodeImage returns Tensor3D for 3-channel images
const image = tf.node.decodeImage(imageBuffer, 3);
try {
const predictions = await model.classify(image);
console.log("Predictions:", predictions);
// [
// { className: "Neutral", probability: 0.87 },
// ...
// ]
return predictions;
} finally {
image.dispose(); // Must dispose tensors manually
model.dispose();
}
}
classifyFile("./photo.jpg");
```
--------------------------------
### Classify Image
Source: https://github.com/infinitered/nsfwjs/blob/master/README.md
Classifies an image using the loaded NSFWJS model. It accepts various image inputs and returns an array of predictions with their confidence levels.
```APIDOC
## `classify` an image
This function can take any browser-based image elements (`
`, `