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.
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-argongemini-3.8-flash(and the oldergemini-3.7-flash,gemini-3.6-flash, andgemini-3.5-flash)gemini-3.5-flash-lite(and the oldergemini-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:
Prompt blocked (
PromptFeedback): The input prompt violated safety filters before the model generated any output. No response candidates are returned.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 evaluatedHarmCategory.probability: A discrete rating (NEGLIGIBLE,LOW,MEDIUM, orHIGH).blocked:trueif 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 from0.0to1.0.severity: A discrete severity level (NEGLIGIBLE,LOW,MEDIUM, orHIGH).severityScore: A floating-point severity score from0.0to1.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 == SAFETYorPromptBlockedExceptionand display a friendly message informing the user that the request couldn't be fulfilled under your content guidelines.Use
BLOCK_NONEfor custom moderation: If you already have your own client-side or server-side moderation pipeline, set thresholds toBLOCK_NONEto receive the model'ssafetyRatingswithout automated blocking, allowing your app to enforce custom moderation policies.Review Terms of Service: If you use less restrictive settings (
BLOCK_ONLY_HIGHorBLOCK_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).