# How Stable Diffusion's Safety Checker Detects and Filters NSFW Content

> Discover how Stable Diffusion's safety checker uses CLIP and a linear classifier to detect and filter NSFW content, ensuring safe image generation. Learn about the process and its effectiveness.

- Repository: [CompVis - Computer Vision and Learning LMU Munich/stable-diffusion](https://github.com/CompVis/stable-diffusion)
- Tags: deep-dive
- Published: 2026-03-01

---

**Stable Diffusion uses the `StableDiffusionSafetyChecker` class from the Hugging Face *diffusers* library, which employs a CLIP ViT-L/14 encoder and a linear classifier to detect NSFW concepts in generated images and replace them with neutral placeholders.**

The CompVis/stable-diffusion repository orchestrates this safety mechanism within its inference scripts, particularly in [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py). While the repository handles the integration, the actual detection logic resides in the external `diffusers` package, making it essential to understand how these components interact to filter inappropriate content.

## Overview of the Stable Diffusion Safety Checker

The safety system is implemented through the `StableDiffusionSafetyChecker` class, which is not defined within the CompVis repository itself but imported from the Hugging Face `diffusers` library. This design separates the core diffusion model from the content filtering logic, allowing the safety checker to be updated independently.

When you run the [`txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/txt2img.py) script, the safety checker is instantiated using a pretrained model identifier:

```python
from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker

safety_checker = StableDiffusionSafetyChecker.from_pretrained(safety_model_id)

```

This initialization loads the CLIP-based vision encoder and the classification head that have been trained on a curated dataset of safe versus not-safe images.

## How the Safety Checker Works

### Model Architecture

Internally, `StableDiffusionSafetyChecker` relies on a **CLIP ViT-L/14** visual encoder to convert input images into high-dimensional embeddings. These embeddings are then passed through a lightweight linear classifier that outputs probabilities for NSFW concepts. The architecture leverages CLIP's robust visual understanding capabilities, fine-tuned specifically for content safety detection.

### Detection Process

When processing generated images, the safety checker performs the following steps:

1. **Embedding Generation**: The input image tensor is processed through the CLIP encoder to produce visual embeddings.
2. **Classification**: The linear classifier evaluates these embeddings against predefined NSFW concept categories.
3. **Flagging**: If the classifier predicts an NSFW concept with sufficient confidence, the corresponding entry in the `has_nsfw_concept` list is set to `True`.

## Implementing NSFW Filtering in txt2img.py

The CompVis repository demonstrates practical integration in [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py), where the safety checker is applied to all generated outputs before saving.

### Loading the Safety Model

At line 22 of [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py), the safety checker is imported and prepared for use:

```python
from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker

```

The script expects a `safety_model_id` (typically `"CompVis/stable-diffusion-safety-checker"`) to load the pretrained weights.

### Running the Safety Check

After the diffusion sampling completes, the generated images undergo safety screening at lines 90–95:

```python
x_checked_image, has_nsfw_concept = safety_checker(
    images=x_image,
    clip_input=safety_checker_input.pixel_values
)

```

Here, `x_image` contains the generated image tensor, while `safety_checker_input.pixel_values` provides the CLIP-preprocessed pixel values required for encoding. The function returns both the potentially filtered images and a boolean list indicating which images triggered NSFW flags.

The same checking mechanism is also applied at line 317 for images generated via DDIM or DDPM samplers, ensuring consistent filtering across different inference methods.

## Handling Flagged Content

When the safety checker identifies NSFW content (`has_nsfw_concept[i] == True`), it automatically replaces the offending image with a neutral "safe" placeholder—typically a gray or black image tensor. This replacement happens within the `safety_checker` call, ensuring that downstream code only receives safe content unless explicitly configured otherwise.

The calling script can then decide how to handle the flags:
- **Drop**: Remove flagged images from the output batch entirely
- **Replace**: Keep the safe placeholder
- **Post-process**: Apply additional filtering or logging based on the `has_nsfw_concept` list

In the reference [`txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/txt2img.py) implementation, the script returns the filtered batch together with the NSFW flags, allowing users to inspect which images were flagged while ensuring no unsafe content is saved to disk.

## Summary

- **Stable Diffusion's safety checker** is implemented via the `StableDiffusionSafetyChecker` class from the Hugging Face `diffusers` library, not within the CompVis repository itself.
- **Detection mechanism** uses a CLIP ViT-L/14 encoder combined with a linear classifier trained to identify NSFW visual concepts in generated images.
- **Integration point** occurs in [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py) at lines 22 and 90–95, where the checker is loaded and applied to all generated outputs before saving.
- **Filtering behavior** automatically replaces flagged images with neutral gray placeholders and returns boolean flags indicating which images contained NSFW content.
- **External dependency**: The actual model weights and classification logic reside in the `diffusers` package, specifically at [`src/diffusers/pipelines/stable_diffusion/safety_checker.py`](https://github.com/CompVis/stable-diffusion/blob/main/src/diffusers/pipelines/stable_diffusion/safety_checker.py).

## Frequently Asked Questions

### How do I disable the NSFW filter in Stable Diffusion?

Disabling the safety checker is not recommended for production environments, but you can bypass it by setting `safety_checker=None` when loading the pipeline in the `diffusers` library, or by modifying [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py) to skip the safety check call at lines 90–95. Note that removing this protection may violate content policies and terms of service.

### What model does the Stable Diffusion safety checker use?

The safety checker utilizes a **CLIP ViT-L/14** vision encoder combined with a lightweight linear classification head. This architecture leverages CLIP's pre-trained visual understanding capabilities, fine-tuned specifically on a curated dataset to distinguish between safe and not-safe image categories.

### Where is the safety checker code located?

While the CompVis/stable-diffusion repository orchestrates the safety check in [`scripts/txt2img.py`](https://github.com/CompVis/stable-diffusion/blob/main/scripts/txt2img.py), the actual implementation of `StableDiffusionSafetyChecker` resides in the Hugging Face `diffusers` library at [`src/diffusers/pipelines/stable_diffusion/safety_checker.py`](https://github.com/CompVis/stable-diffusion/blob/main/src/diffusers/pipelines/stable_diffusion/safety_checker.py). The CompVis repository imports and uses this external class rather than implementing its own detection logic.

### Why are my images being flagged as NSFW when they are not?

False positives can occur because the linear classifier operates on visual embeddings that may misinterpret artistic styles, skin tones, or specific visual patterns as NSFW concepts. The model was trained on a specific dataset that may not cover all cultural contexts or artistic representations. If you encounter frequent false positives, you may need to adjust the safety checker threshold or implement additional post-processing logic based on the `has_nsfw_concept` flags returned by the checker.