Nsfw Image Check Node
Gate NSFW output and swap in a warning image
- image_requires_in
- custom_image_out
- image_requires_out
- corresponding_filter_entries
Most NSFW "detectors" in ComfyUI are the thing people are trying to remove - the black-box censor baked into nodes like ReActor that turns a face swap into a solid black rectangle the second it sees skin. This node is the opposite. You add it on purpose, because you actually want a gate: you're running a public-facing app, feeding a Discord bot, or batch-generating for a client and something needs to catch the explicit frames before they ship. If you're just generating for yourself, you don't need this. If you're the one on the hook for what leaves the machine, it's genuinely useful.
The honest framing up front: the name oversells it. It doesn't "block" anything in a hard-stop sense. When detection trips, it swaps the image out - for a built-in warning image, or one you supply - and passes that downstream instead of the real one. Your graph keeps flowing; the offending frame just doesn't make it through. Think of it as a filter valve, not a kill switch.
How it works
Under the hood it's a stripped-down piece of deepghs/imgutils, the anime-image toolkit. The author kept only the classifier code and bundled the model straight into the plugin folder, so there's no runtime download - that's why it stays lightweight. The classifier scores your image across a handful of NSFW categories and compares each score against a threshold. Cross the line, and the swap fires.
Those category names are a tell about its lineage: r18, hentai, furry, genitalia, porn, sexy. That's booru taxonomy - the vocabulary of Danbooru and e621, the anime and furry imageboards that trained the whole open-source anime ecosystem. So this thing is tuned for illustrated content. It'll be sharpest on anime and 2D output and noticeably shakier on photoreal renders, which is worth knowing before you trust it as your only line of defense.
The inputs and outputs that matter
You wire image_requires_in off a VAE Decode or a Load Image - that's the frame being checked. The one decision that shapes everything is filter_choose:
- A single filter (
r18_nsfw_check,hentai_nsfw_check,porn_nsfw_check, and so on) - checks that one category only. Fast, focused, the default isr18_nsfw_check. auto_nsfw_check- runs every category whose matching..._enabledtoggle is on. This is the only mode where the per-category..._thresholdand..._enabledswitches actually do anything. In single-filter mode they're ignored, which trips people up.
Each ..._threshold runs 0 to 1, default 0.5. Counterintuitively, lower is stronger - a lower threshold trips more easily, catching more but also flagging more borderline frames as false positives. Nudge it up if it's too twitchy, down if things are slipping past.
custom_image_out (optional) lets you feed your own replacement image instead of the default warning. There's also a jankier path baked in: drop .jpg files named as sequential numbers into the pack's img folder and it'll pull from those.
Two outputs. image_requires_out is the IMAGE that continues down your graph - the original if it's clean, the warning/replacement if it isn't. corresponding_filter_entries is a STRING naming which filters tripped; wire it into a Show Text node for logging, or into a switch if you want to branch on it.
Installing it
ComfyUI Manager: search nsfw-image-check-comfyui, install, restart. By hand:
cd ComfyUI/custom_nodes
git clone https://github.com/fallingmeteorite/nsfw-image-check-comfyui.git
cd nsfw-image-check-comfyui
pip install -r requirements.txt
Then restart ComfyUI. There's also comfy node registry-install nsfw-image-check-comfyui if you use the CLI. No separate model download - it ships inside the plugin folder.
Common issues
The big one is expectations. The README says the plugin is "stable, so it hasn't been updated" - read that as finished and unmaintained. Don't expect fixes or new categories. The booru-trained classifier means photoreal content is a weak spot; test it on your actual output rather than assuming. And the single most common confusion: setting per-category thresholds and enables, then wondering why nothing changed - those only take effect under auto_nsfw_check. Pick that mode, or accept the single-filter defaults. Finally, this is a moderation aid, not a guarantee - no classifier catches everything, so treat it as one layer, not the whole wall.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| image_requires_in | IMAGE | — | |
| custom_image_outopt | IMAGE | — | |
| enabled_checkopt | BOOLEAN | true | — |
| r18_thresholdopt | FLOAT | 0.500–1 | — |
| hentai_thresholdopt | FLOAT | 0.500–1 | — |
| furry_thresholdopt | FLOAT | 0.500–1 | — |
| genitalia_thresholdopt | FLOAT | 0.500–1 | — |
| porn_thresholdopt | FLOAT | 0.500–1 | — |
| sexy_thresholdopt | FLOAT | 0.500–1 | — |
| r18_enabledopt | BOOLEAN | true | — |
| hentai_enabledopt | BOOLEAN | true | — |
| furry_enabledopt | BOOLEAN | true | — |
| genitalia_enabledopt | BOOLEAN | true | — |
| porn_enabledopt | BOOLEAN | true | — |
| sexy_enabledopt | BOOLEAN | true | — |
| filter_chooseopt | COMBO | r18_nsfw_check | 7 options: r18_nsfw_check, hentai_nsfw_check, furry_nsfw_check, genitalia_nsfw_check, porn_nsfw_check, sexy_nsfw_check, +1 |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image_requires_out | IMAGE | — |
| corresponding_filter_entries | STRING | — |