LLM API Content Moderation and Safety Filters: Cross-Provider Comparison of Refusal Behavior, Moderation APIs, and Content Policies
We compared content moderation approaches across OpenAI, Anthropic, DeepSeek, DashScope, and Kimi — covering moderation API endpoints, refusal response formats, content policy categories, and what operators need to know when routing requests across providers with different safety policies.
Every LLM API provider moderates content differently. OpenAI gives you a free moderation endpoint with per-category scores. Anthropic trains constitutional classifiers into its models and handles refusals inline. DeepSeek and Kimi apply server-side filters shaped by Chinese regulatory requirements. DashScope layers an optional Guardrails service on top of its built-in policy enforcement.
If you route requests across multiple providers, you will eventually hit a case where Provider A accepts a prompt that Provider B refuses. This reference maps each provider's moderation approach so you can build routing logic that handles these asymmetries without surprising your users.
OpenAI-compatible means a provider exposes a chat-completions endpoint whose request and response shape matches the OpenAI API contract closely enough that an unmodified OpenAI SDK call works against it after swapping three values: API key, base URL, and model name. The minimum surface in practice is POST /v1/chat/completions with messages, model, and an OpenAI-shaped streaming response.
TL;DR Comparison Table
| Provider | Dedicated Moderation API | Inline Moderation | Refusal Format | Content Categories | Configurable Filters |
|---|---|---|---|---|---|
| OpenAI | Yes — omni-moderation-latest (free) | Yes — moderation param in Responses API | HTTP 200 + refusal text in response | hate, harassment, self-harm, sexual, violence (+ subcategories) | No (model-level) |
| Anthropic | No | Yes — constitutional classifiers | HTTP 200 + stop_reason: "end_turn" with polite refusal | CBRN, weapons, child safety, election interference, fraud | No (model-level, classifier-level) |
| DeepSeek | No | Yes — server-side filters | HTTP 400 or refusal text in response body | China-regulated categories + general safety | No |
| DashScope | No (separate Guardrails product) | Yes — built-in policy + optional Guardrails | HTTP 400 DataInspectionFailed (Guardrails); refusal text (built-in) | China-regulated categories, customizable tags via Guardrails | Partially (Guardrails tag management) |
| Kimi | No | Yes — server-side filters | Refusal text in response body | China-regulated categories + general safety | No |
OpenAI: Moderation Endpoint + Inline Scoring
OpenAI is unique among major providers in offering a standalone, free moderation endpoint. The omni-moderation-latest model accepts both text and image inputs (up to 20 MB per image) and returns per-category flags and confidence scores without generating a completion.
Standalone Moderation
from openai import OpenAI
client = OpenAI()
result = client.moderations.create(
model="omni-moderation-latest",
input="text to classify"
)
print(result.results[0].flagged) # True/False
print(result.results[0].categories) # per-category booleans
print(result.results[0].category_scores) # per-category 0.0–1.0
The endpoint is free and does not count toward your usage quota. Categories include hate, harassment, self-harm, sexual, violence, and subcategories like hate/threatening, self-harm/instructions, sexual/minors, and violence/graphic.
Inline Moderation with Responses API
Since mid-2026, OpenAI also supports inline moderation by passing a moderation parameter in Responses API calls:
response = client.responses.create(
model="gpt-5.6",
input=[{"role": "user", "content": "..."}],
moderation={"model": "omni-moderation-latest"}
)
# Check input and output moderation
input_mod = response.moderation.input # flagged, categories, scores
output_mod = response.moderation.output # flagged, categories, scores
This returns moderation scores for both the input and the generated output in a single API call. The model still generates normally — treat the moderation signals as input to your application's content policy, not as an automatic block.
Key detail for operators: Inline moderation scores arrive after the full response is generated. If you stream a response, moderation results are not included with partial deltas. A response that discusses harmful content in a safety-aware way (e.g., a refusal explaining why something is dangerous) can still trigger a moderation flag. Source: OpenAI Moderation docs, retrieved 2026-08-10
Anthropic: Constitutional Classifiers
Anthropic does not offer a standalone moderation endpoint. Instead, Claude models are trained with Constitutional AI principles and defended by constitutional classifiers — input and output classifiers that filter requests at inference time.
How Refusals Work
When Claude determines a request violates its content policy, it returns a normal HTTP 200 response with stop_reason: "end_turn" containing a polite refusal. There is no special error code or HTTP status for content moderation refusals — the refusal is indistinguishable from a normal completion at the HTTP level.
{
"content": [
{
"type": "text",
"text": "I can't help with that request. Creating instructions for weapons could cause serious harm..."
}
],
"stop_reason": "end_turn"
}
Constitutional Classifiers
Anthropic published research on constitutional classifiers in early 2025. These are separate AI systems trained on synthetically generated data that guard models against jailbreaks. Key findings from their bug bounty program:
- 183 participants spent over 3,000 hours attempting to find universal jailbreaks
- No universal jailbreak was discovered during the two-month test period
- Updated classifiers achieved robustness with only a 0.38% increase in refusal rates over baseline
With the release of Claude Fable 5 and Mythos 5 in mid-2026, Anthropic introduced a new generation of classifiers that detect potential misuse including jailbreak attempts. Source: Anthropic Constitutional Classifiers research, retrieved 2026-08-10
Content Policy Categories
Anthropic's Acceptable Use Policy covers:
- CBRN (chemical, biological, radiological, nuclear) threats
- Weapons and explosives
- Child sexual abuse material (CSAM)
- Election interference and political manipulation
- Fraud and deception
- Malware and cyberattacks
Unlike OpenAI, Anthropic does not expose per-category scores. You cannot programmatically determine why Claude refused a request — only that it did.
DeepSeek: Server-Side Filtering
DeepSeek applies content filtering server-side on all API requests. As a Chinese AI company, DeepSeek's content moderation is shaped by China's content regulation framework, which mandates filtering across categories including political sensitivity, violence, and other locally regulated topics.
Refusal Behavior
DeepSeek's refusal responses vary. The API may return:
- A normal HTTP 200 response with refusal text like "Sorry, that's beyond my current scope. Let's chat about something else?"
- An HTTP 400 error for content that triggers hard policy violations
{
"choices": [
{
"message": {
"role": "assistant",
"content": "Sorry, that's beyond my current scope. Let's chat about something else?"
},
"finish_reason": "stop"
}
]
}
What Operators Should Know
- DeepSeek does not expose a moderation API or per-category scores
- Content filtering is not configurable through the API
- Refusals are indistinguishable from normal completions at the HTTP level (when soft refusals are returned)
- The filtering scope reflects Chinese regulatory requirements, which differ materially from Western provider policies
- Self-hosted DeepSeek open-weight models (V4, V4-0324) do not include these API-level filters — filtering applies only to the hosted API
Source: DeepSeek API docs, retrieved 2026-08-10
DashScope (Alibaba Cloud): Built-in Policy + Guardrails Service
DashScope (Alibaba Cloud Model Studio) operates a two-layer moderation system. A built-in content policy enforces baseline compliance on all Qwen model API calls. On top of this, operators can optionally enable the Guardrails service for more granular control.
Built-in Content Policy
All DashScope API calls pass through baseline content moderation aligned with Chinese regulatory requirements. When the built-in filter triggers, the model may return a refusal in the response body with finish_reason: "stop".
Guardrails Service (Optional)
The Guardrails service provides additional moderation with configurable tags. To enable it, pass the X-DashScope-DataInspection header:
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="qwen-plus",
messages=[
{"role": "user", "content": "..."}
],
extra_headers={
"X-DashScope-DataInspection": '{"input":"cip","output":"cip"}'
}
)
When Guardrails triggers, DashScope returns an HTTP 400 with error code DataInspectionFailed (OpenAI-compatible mode) or data_inspection_failed:
{
"error": {
"code": "data_inspection_failed",
"message": "Output data may contain inappropriate content.",
"type": "data_inspection_failed"
}
}
Configurable Tag Management
Unlike other providers, DashScope's Guardrails lets operators enable or disable specific moderation tags based on their application requirements. Custom security policy configurations are available for enterprise users. This makes DashScope the most configurable Chinese provider for content moderation, though core policy compliance remains mandatory.
Source: Alibaba Cloud Guardrails service docs, retrieved 2026-08-10
Kimi (Moonshot AI): Inline Safety Filters
Kimi's API applies server-side content filtering on all requests, consistent with Chinese regulatory requirements. Like DeepSeek, Kimi does not expose a moderation API or per-category scores.
Refusal Behavior
Kimi K3 returns refusal messages inline in the response body. The API documentation states that the model "will reject any questions involving terrorism, racial discrimination, pornography, incitement to violence, etc."
Refusals arrive as normal HTTP 200 responses with the refusal text as the assistant's message:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "I'm sorry, but I can't assist with that request..."
},
"finish_reason": "stop"
}
]
}
What Operators Should Know
- No dedicated moderation endpoint
- Content filtering is not configurable via the API
- Refusal behavior is inline (HTTP 200 + refusal text), not error-level
- When Kimi K3 weights are released, self-hosted deployments will not include API-level filtering
Source: Kimi Platform docs, retrieved 2026-08-10
Impact on Multi-Provider Routing
When you route requests across providers with different content policies, three practical problems arise:
1. Detecting Moderation Refusals
The fundamental challenge is that most providers return refusals as normal HTTP 200 responses. Only DashScope with Guardrails enabled returns a distinct HTTP 400 error code. For OpenAI, Anthropic, DeepSeek, and Kimi, you need to parse the response text to determine whether the model actually answered or politely refused.
Approaches we have seen operators use:
- Keyword matching — checking for phrases like "I can't help with that," "beyond my current scope," or "I'm unable to"
- OpenAI inline moderation — using the
moderationparameter to get machine-readable flags alongside the generation - Response length heuristics — moderation refusals tend to be short (under 200 tokens) relative to genuine answers
2. Asymmetric Refusal Handling
A prompt that passes OpenAI's moderation may be refused by a Chinese provider, and vice versa. The policy spaces overlap but do not align:
| Scenario | OpenAI | Anthropic | Chinese Providers |
|---|---|---|---|
| Political content (Western perspective) | Generally allowed | Generally allowed | May be filtered |
| Political content (Chinese sensitivity) | Generally allowed | Generally allowed | Filtered |
| Weapons/explosives | Moderated | Refused | Refused |
| CBRN content | Moderated | Refused | Refused |
| Adult content | Moderated | Refused | Refused |
| Historical/educational violence | Usually allowed | Usually allowed | May be filtered |
3. Fallback Strategy
When a primary provider refuses a request, your routing layer needs a policy decision:
- Retry on fallback provider — useful when the refusal is provider-specific (e.g., political sensitivity on Chinese providers). Risk of policy arbitrage if not logged.
- Surface the refusal — pass the moderation refusal back to the user. Safer from a compliance perspective.
- Log and alert — record moderation events for audit trails regardless of whether you retry.
TheRouter supports provider fallback routing that can be configured to handle different error types. When a provider returns an error, the routing layer can fall back to an alternate provider. For content moderation refusals that arrive as HTTP 200, operators need application-level logic to detect refusals before the routing layer can act.
Decision Matrix: Choosing a Moderation Approach
| Your Need | Recommended Approach |
|---|---|
| Pre-screen user inputs before generation | OpenAI moderation endpoint (free, standalone) |
| Get moderation signals with every generation | OpenAI inline moderation (moderation parameter) |
| Maximum control over moderation categories | DashScope Guardrails (configurable tags) |
| Audit trail of all moderation events | OpenAI moderation endpoint + application logging |
| Route around provider-specific refusals | Application-level refusal detection + fallback routing |
| Self-hosted model without content filters | DeepSeek or Kimi open-weight models |
FAQ
How do I programmatically detect a content moderation refusal?
OpenAI's inline moderation returns machine-readable flagged booleans and per-category scores. For all other providers, you need to parse the response text. Check for common refusal patterns, unusually short responses, or use a lightweight classifier on the output. DashScope with Guardrails is the exception — it returns a distinct HTTP 400 error code.
Can I use OpenAI's moderation endpoint with other providers' outputs?
Yes. The moderation endpoint accepts any text input regardless of which model generated it. Some operators run all LLM outputs through OpenAI's moderation endpoint as a second-pass safety check, regardless of the originating provider. The endpoint is free and does not require a generation API key — any OpenAI API key works.
Why does the same prompt get different moderation results across providers?
Each provider maintains independent content policies, trains different safety classifiers, and operates under different regulatory frameworks. Chinese providers (DeepSeek, DashScope, Kimi) must comply with Chinese content regulations, which cover categories that Western providers do not filter. Western providers (OpenAI, Anthropic) have their own policy categories that may not align with Chinese requirements.
What happens to content moderation in streaming responses?
OpenAI's inline moderation scores arrive after the full response is generated — they are not included with partial streaming deltas. If a response triggers a moderation flag mid-stream, your application will have already started sending tokens to the user. For providers that return inline refusals (Anthropic, DeepSeek, Kimi), the refusal text streams normally as part of the response.
Does TheRouter handle content moderation refusals in its routing?
TheRouter routes OpenAI-compatible requests through configured providers and supports fallback routing when a provider returns an error. For hard errors like DashScope's HTTP 400 DataInspectionFailed, the routing layer can trigger a fallback. For soft refusals (HTTP 200 with refusal text), detection and routing decisions happen at the application layer, since the response is technically successful from the HTTP perspective.
Are there regional differences in content moderation strictness?
Yes. Chinese providers operate under mandatory content regulation that covers political sensitivity, historical events, and other categories that Western providers generally do not filter. DashScope's international endpoint (dashscope-intl.aliyuncs.com) applies the same core content policies as the domestic endpoint. When routing between Chinese and Western providers, operators should test their specific use cases against both policy sets.
Further Reading
- LLM API Error Codes Across Providers — HTTP-level error handling, including moderation-triggered errors
- AI Agent Governance and Runtime Guardrails Comparison — governance controls for agentic coding workflows
- LLM API Providers Comparison 2026 — comprehensive provider overview including pricing and rate limits
- OpenAI to TheRouter Migration Guide — migrating from direct OpenAI usage to multi-provider routing
- DeepSeek API Complete Guide — full DeepSeek API reference including error handling
- Aliyun Bailian (DashScope) API Guide — DashScope setup, models, and integration patterns
- Kimi K3 API Integration Guide — Kimi K3 setup and API usage
- Anthropic Claude API Complete Guide — Claude API reference and integration