Understand and configure safety settings

Gemini models are designed to prioritize safety. However, they can still generate harmful responses, especially when they're explicitly prompted. To further enhance safety and minimize misuse, you can configure safety filters to block potentially harmful responses.

Two layers of safety protections are provided:

  • Built-in core protections:

    • All Gemini models feature built-in protections against severe harms (such as child exploitation, cyberattacks, and dangerous weapons).
    • These protections are always active, applied automatically to all prompts and responses, and can't be modified or disabled.
  • Configurable safety filters:

    • The Gemini API provides additional configurable safety filters which you define using safety settings in your app.
    • These settings let you control the threshold at which content is blocked across four main harm categories: Harassment, Hate speech, Sexually explicit content, and Dangerous content.

Jump to code samples

Important safety concepts

When working with safety for Gemini models, here are some important concepts to understand:

  • Safety settings: The configuration you define in your app code specifying which harm categories to monitor and at what threshold to block content.

  • Safety filters: The server-side classifiers that evaluate prompts and model responses against Google's safety dimensions. The filters block content based on your configured safety settings.

  • Safety ratings: The evaluation metadata returned by the model in the response object. The ratings indicate the probability and severity of potential harm detected for each harm category.

Supported models

  • gemini-4-argon
  • gemini-3.8-flash (and the older gemini-3.7-flash, gemini-3.6-flash, and gemini-3.5-flash)
  • gemini-3.5-flash-lite (and the older gemini-3.1-flash-lite)
  • gemini-nano-banana-2.1 (Nano Banana 2.1)
  • gemini-3.1-flash-image (Nano Banana 2)
  • gemini-3.1-flash-lite-image (Nano Banana 2 Lite)
  • gemini-3-pro-image (Nano Banana Pro)

The gemini-3.1-pro-preview model as well as the general-use and image-generating Gemini 2.5 models (which are deprecated) also support this capability.



Configure safety settings in your app

Click your Gemini API provider to view provider-specific content and code on this page.

You configure safety settings as part of initializing a GenerativeModel instance. The configuration is maintained for the lifetime of that model instance.

Learn about the available harm categories and the thresholds that you can set for each category later on this page.

Swift

Configure SafetySetting when creating a GenerativeModel instance:


import FirebaseAILogic

let safetySettings = [
  SafetySetting(harmCategory: .harassment, threshold: .blockOnlyHigh),
  SafetySetting(harmCategory: .hateSpeech, threshold: .blockMediumAndAbove)
]

// Specify the safety settings as part of creating the `GenerativeModel` instance.
let model = FirebaseAI.firebaseAI(backend: .googleAI()).generativeModel(
  modelName: "GEMINI_MODEL_NAME",
  safetySettings: safetySettings
)

// ...

Kotlin

Configure SafetySetting when creating a GenerativeModel instance:


// ...

val safetySettings = listOf(
    SafetySetting(HarmCategory.HARASSMENT, HarmBlockThreshold.ONLY_HIGH),
    SafetySetting(HarmCategory.HATE_SPEECH, HarmBlockThreshold.MEDIUM_AND_ABOVE)
)

// Specify the safety settings as part of creating the `GenerativeModel` instance.
val model = Firebase.ai(backend = GenerativeBackend.googleAI()).generativeModel(
    modelName = "GEMINI_MODEL_NAME",
    safetySettings = safetySettings
)

// ...

Java

Configure SafetySetting when creating a GenerativeModel instance:


// ...

List safetySettings = List.of(
    new SafetySetting(HarmCategory.HARASSMENT, HarmBlockThreshold.ONLY_HIGH),
    new SafetySetting(HarmCategory.HATE_SPEECH, HarmBlockThreshold.MEDIUM_AND_ABOVE)
);

// Specify the safety settings as part of creating the `GenerativeModel` instance.
GenerativeModelFutures model = GenerativeModelFutures.from(
    FirebaseAI.getInstance(GenerativeBackend.googleAI())
        .generativeModel(
            /* modelName */ "GEMINI_MODEL_NAME",
            /* generationConfig is optional */ null,
            safetySettings
        )
);

// ...

Web

Configure SafetySetting when creating a GenerativeModel instance:


import { HarmBlockThreshold, HarmCategory, getAI, getGenerativeModel, GoogleAIBackend } from "firebase/ai";

// ...

const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

const safetySettings = [
  {
    category: HarmCategory.HARM_CATEGORY_HARASSMENT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH,
  },
  {
    category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
    threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
  },
];

// Specify the safety settings as part of creating the `GenerativeModel` instance.
const model = getGenerativeModel(ai, {
  model: "GEMINI_MODEL_NAME",
  safetySettings,
});

// ...

Dart

Configure SafetySetting when creating a GenerativeModel instance:


import 'package:firebase_ai/firebase_ai.dart';

final safetySettings = [
  SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high),
  SafetySetting(HarmCategory.hateSpeech, HarmBlockThreshold.medium),
];

// Specify the safety settings as part of creating the `GenerativeModel` instance.
final model = FirebaseAI.googleAI().generativeModel(
  model: 'GEMINI_MODEL_NAME',
  safetySettings: safetySettings,
);

// ...

Unity

Configure SafetySetting when creating a GenerativeModel instance:


// ...

var safetySettings = new SafetySetting[] {
  new SafetySetting(HarmCategory.Harassment, SafetySetting.HarmBlockThreshold.OnlyHigh),
  new SafetySetting(HarmCategory.HateSpeech, SafetySetting.HarmBlockThreshold.MediumAndAbove)
};

// Specify the safety settings as part of creating the `GenerativeModel` instance.
var ai = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI());
var model = ai.GetGenerativeModel(
  modelName: "GEMINI_MODEL_NAME",
  safetySettings: safetySettings
);

// ...



Available harm categories

The safety filters evaluate prompts and model responses against the following configurable harm categories:

Harm category Description
HARM_CATEGORY_HARASSMENT Negative, threatening, intimidating, bullying, or abusive comments targeting an individual or identity.
HARM_CATEGORY_HATE_SPEECH Content that attacks, demeans, promotes hatred, or incites violence against individuals or groups based on protected attributes (such as race, ethnic origin, religion, disability, age, nationality, veteran status, sexual orientation, or gender identity).
HARM_CATEGORY_SEXUALLY_EXPLICIT Contains references to sexual acts, pornography, or other lewd and erotic content.
HARM_CATEGORY_DANGEROUS_CONTENT Promotes, facilitates, encourages, or provides instructions for harmful acts, illegal goods and services, weapons, self-harm, or dangerous activities.
HARM_CATEGORY_CIVIC_INTEGRITY Content that might be used to mislead voters or undermine civic and electoral processes. (Supported in select models and regions).

Non-configurable safety filters

In addition to configurable categories, all requests pass through system-level filters that can't be adjusted:

  • Child Sexual Abuse Material (CSAM) / Prohibited content: Prompts or responses flagged for prohibited content are immediately blocked (PROHIBITED_CONTENT).

  • Sensitive Personally Identifiable Information (SPII): Responses that risk exposing sensitive personal data (such as financial account numbers or national IDs) are blocked (SPII).



Set thresholds

For each harm category that you want to control for in your app, you need to set a threshold. If the evaluated content meets or exceeds that threshold, the content is blocked.

How safety evaluation works: Probability vs. severity

Safety filters evaluate content across two distinct dimensions:

  • Probability: The model's confidence that content falls within a given harm category.

  • Severity: The magnitude or degree of potential harm should the content be harmful.

Each dimension is assigned one of these levels: NEGLIGIBLE, LOW, MEDIUM, or HIGH.

Content can have a high probability with low severity level (for example, mild comedic banter or friendly insults) or low probability with high severity level (for example, medical or historical discussions mentioning violence).

Available harm block thresholds

You can set any of the following thresholds for the harm categories that you want to control for in your app:

Threshold Description Allowed levels
BLOCK_LOW_AND_ABOVE Most restrictive.
Blocks content when probability (or severity) is LOW, MEDIUM, or HIGH.
Allows only NEGLIGIBLE
BLOCK_MEDIUM_AND_ABOVE Moderate restriction.
Blocks content when probability (or severity) is MEDIUM or HIGH.
Allows NEGLIGIBLE and LOW
BLOCK_ONLY_HIGH Least restrictive active filter.
Blocks content only when probability (or severity) is HIGH.
Allows NEGLIGIBLE, LOW, and MEDIUM
BLOCK_NONE Automated response blocking is disabled for this category. Safety ratings metadata is still calculated and returned with the response so your app can perform custom moderation. All content allowed
OFF Turns off the safety filter for this category completely. No automated blocking occurs and no safety rating metadata is returned. All content allowed



Inspect safety ratings and handle blocked content

Content can be blocked at two stages during a request:

  1. Prompt blocked (PromptFeedback): The input prompt violated safety filters before the model generated any output. No response candidates are returned.

  2. Response candidate blocked (finishReason == SAFETY): The model evaluated or generated a candidate response that exceeded your configured threshold. The generated candidate text is cleared or redacted.

The SafetyRating object

Every evaluated prompt or response candidate contains an array of SafetyRating objects. Each rating provides the following:

  • Properties available with both Gemini Developer API and Agent Platform Gemini API (formerly Vertex AI):

    • category: The evaluated HarmCategory.

    • probability: A discrete rating (NEGLIGIBLE, LOW, MEDIUM, or HIGH).

    • blocked: true if this specific rating caused the content to be blocked.

  • Additional properties available with the Agent Platform Gemini API (formerly Vertex AI):

    • probabilityScore: A floating-point confidence score from 0.0 to 1.0.

    • severity: A discrete severity level (NEGLIGIBLE, LOW, MEDIUM, or HIGH).

    • severityScore: A floating-point severity score from 0.0 to 1.0.

Example SafetyRating object

The following example illustrates the raw JSON response payload when a candidate is blocked by safety filters:

{
  "candidates": [
    {
      "finishReason": "SAFETY",
      "safetyRatings": [
        {
          "category": "HARM_CATEGORY_HARASSMENT",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_HATE_SPEECH",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
          "probability": "HIGH",
          "blocked": true
        }
      ]
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 24,
    "totalTokenCount": 24
  }
}

Catch safety errors in code

When content is blocked, the client SDKs surface the block as an exception or error code so your app can handle it gracefully.

Swift

You can catch GenerateContentError.promptBlocked or GenerateContentError.responseStoppedEarly:

do {
  let response = try await model.generateContent("Your prompt here")
  print(response.text ?? "No text generated.")
} catch GenerateContentError.promptBlocked(let response) {
  // The input prompt was blocked
  if let feedback = response.promptFeedback {
    let reason = feedback.blockReason?.rawValue ?? "unknown"
    print("Prompt blocked for reason: \(reason)")
    for rating in feedback.safetyRatings {
      let cat = rating.category.rawValue
      let prob = rating.probability.rawValue
      print("Category: \(cat), probability: \(prob)")
    }
  }
} catch GenerateContentError.responseStoppedEarly(let reason, let response) {
  // Candidate response was blocked or stopped early
  if reason == .safety {
    print("Response blocked due to safety.")
    if let candidate = response.candidates.first {
      for rating in candidate.safetyRatings where rating.blocked {
        print("Blocked by category: \(rating.category.rawValue)")
      }
    }
  }
} catch {
  print("Unexpected error: \(error)")
}

Kotlin

You can catch PromptBlockedException or inspect candidate.finishReason:

try {
  val response = model.generateContent("Your prompt here")
  val candidate = response.candidates.firstOrNull()

  if (candidate?.finishReason == FinishReason.SAFETY) {
    val blockedRating =
      candidate.safetyRatings.firstOrNull { it.blocked }
    println("Response blocked by category: ${blockedRating?.category}")
  } else {
    println(response.text)
  }
} catch (e: PromptBlockedException) {
  val reason = e.response?.promptFeedback?.blockReason
  println("Prompt was blocked: $reason")
} catch (e: Exception) {
  println("Error generating content: ${e.message}")
}

Java

You can catch PromptBlockedException or inspect candidate.getFinishReason():

try {
  GenerateContentResponse response = model.generateContent("Your prompt here").get();
  Candidate candidate = response.getCandidates().isEmpty() ? null : response.getCandidates().get(0);

  if (candidate != null && candidate.getFinishReason() == FinishReason.SAFETY) {
    SafetyRating blockedRating = null;
    for (SafetyRating rating : candidate.getSafetyRatings()) {
      if (Boolean.TRUE.equals(rating.getBlocked())) {
        blockedRating = rating;
        break;
      }
    }
    System.out.println("Response blocked by category: " +
        (blockedRating != null ? blockedRating.getCategory() : "unknown"));
  } else {
    System.out.println(response.getText());
  }
} catch (ExecutionException e) {
  if (e.getCause() instanceof PromptBlockedException) {
    PromptBlockedException pbe = (PromptBlockedException) e.getCause();
    GenerateContentResponse blockedResponse = pbe.getResponse();
    String reason = (blockedResponse != null && blockedResponse.getPromptFeedback() != null)
        ? String.valueOf(blockedResponse.getPromptFeedback().getBlockReason())
        : "unknown";
    System.out.println("Prompt was blocked: " + reason);
  } else {
    System.out.println("Error generating content: " + e.getMessage());
  }
} catch (InterruptedException e) {
  System.out.println("Generation was interrupted: " + e.getMessage());
}

Web

You can inspect promptFeedback and candidate.finishReason:

try {
  const response = await model.generateContent("Your prompt here");

  // Check if the prompt was blocked
  if (response.promptFeedback?.blockReason) {
    console.warn(`Prompt blocked: ${response.promptFeedback.blockReason}`);
    return;
  }

  const candidate = response.candidates?.[0];
  if (candidate?.finishReason === "SAFETY") {
    const blockedRating = candidate.safetyRatings?.find((r) => r.blocked);
    console.warn(`Response blocked by category: ${blockedRating?.category}`);
  } else {
    console.log(response.text);
  }
} catch (error) {
  console.error("Error generating content:", error);
}

Dart

You can inspect promptFeedback and candidate.finishReason:

try {
  final response = await model.generateContent([Content.text('Your prompt here')]);

  // Check if the prompt was blocked
  if (response.promptFeedback?.blockReason != null) {
    print('Prompt blocked: ${response.promptFeedback?.blockReason}');
    return;
  }

  final candidate = response.candidates.firstOrNull;
  if (candidate?.finishReason == FinishReason.safety) {
    final blockedRating =
        candidate?.safetyRatings?.where((r) => r.isBlocked == true).firstOrNull;
    print('Response blocked by category: ${blockedRating?.category.name}');
  } else {
    print(response.text);
  }
} catch (e) {
  print('Error generating content: $e');
}

Unity

You can inspect PromptFeedback and candidate.FinishReason:

try {
  var response = await model.GenerateContentAsync("Your prompt here");

  // Check if the prompt was blocked
  if (response.PromptFeedback?.BlockReason != null) {
    Debug.LogWarning($"Prompt blocked: {response.PromptFeedback.BlockReason}");
    return;
  }

  var candidate = response.Candidates.FirstOrDefault();
  if (candidate?.FinishReason == FinishReason.Safety) {
    var blockedRating = candidate.SafetyRatings?.FirstOrDefault(r => r.Blocked);
    Debug.LogWarning($"Response blocked by category: {blockedRating?.Category}");
  } else {
    Debug.Log(response.Text);
  }
} catch (Exception ex) {
  Debug.LogError($"Error generating content: {ex.Message}");
}



Best practices for responsible app design

  • Defense in depth: Safety filters are a guardrail, not an instruction. Combine safety settings with explicit system instructions and targeted prompt design to guide tone and scope.

  • Graceful user feedback: Never crash or show a blank screen when content is blocked. Detect finishReason == SAFETY or PromptBlockedException and display a friendly message informing the user that the request couldn't be fulfilled under your content guidelines.

  • Use BLOCK_NONE for custom moderation: If you already have your own client-side or server-side moderation pipeline, set thresholds to BLOCK_NONE to receive the model's safetyRatings without automated blocking, allowing your app to enforce custom moderation policies.

  • Review Terms of Service: If you use less restrictive settings (BLOCK_ONLY_HIGH or BLOCK_NONE), ensure your app continues to comply with Google's Prohibited Use Policy.

Other options to control content generation

  • Learn more about prompt design so that you can influence the model to generate output specific to your needs.
  • Configure model parameters to control how the model generates a response, like max output tokens, the probability of repeated output tokens, etc.
  • Set system instructions to steer the behavior of the model. This feature is like a preamble that you add before the model gets exposed to any further instructions from the end user.
  • Pass a response schema along with the prompt to specify a specific output schema. This feature is most commonly used when generating JSON output, but it can also be used for classification tasks (like when you want the model to use specific labels or tags).