← Blog

Claude API Content Moderation Filter: Setup Guide

2026-10-14 · 5 min read · SubToAPI Team

If you're searching for a "Claude API content moderation filter," you're likely trying to classify user-generated content — chat messages, comments, uploads, prompts — as safe or unsafe before it reaches your application or your users. Claude doesn't ship a dedicated moderation endpoint like some other providers, but you can build a reliable moderation filter using the Messages API with a carefully constrained prompt and structured output.

This guide covers the practical setup: how to design the moderation prompt, how to get consistent machine-readable results, how to handle edge cases, and how to wire it into a production pipeline without adding unacceptable latency.

Why Use Claude for Moderation Instead of a Dedicated API

Purpose-built moderation APIs are fast and cheap, but they're often limited to fixed categories (hate, violence, sexual content) with no room for custom policy. Claude-based moderation gives you:

The tradeoff is latency and cost compared to a dedicated classifier, so most teams use Claude moderation as a secondary layer — after a fast keyword/regex filter, before content is published or acted on.

Designing the Moderation Prompt

The key to reliable moderation is a tightly scoped system prompt that forces the model into a classification role, not a conversational one.

{
  "model": "claude-opus-4-5-20251101",
  "max_tokens": 200,
  "system": "You are a content moderation classifier. You do not chat, explain policy, or refuse. For each input, return ONLY a JSON object with: {\"flagged\": boolean, \"categories\": string[], \"severity\": \"low\"|\"medium\"|\"high\", \"reason\": string}. Categories must be chosen from: harassment, hate, violence, sexual, self_harm, spam, pii, jailbreak, other. If content is safe, return flagged: false with empty categories.",
  "messages": [
    {
      "role": "user",
      "content": "Classify this message: \"I'll find out where you live and make you regret it.\""
    }
  ]
}

Keep the system prompt narrow and avoid asking the model to also moderate itself — separate the classifier call from any user-facing generation call.

Getting Structured, Parseable Output

For a moderation filter to be useful in code, you need a guaranteed JSON shape. Two things help a lot:

  1. Explicit schema in the system prompt, as above, with exact field names and types.
  2. Low max_tokens to prevent rambling — 150–250 tokens is enough for a verdict plus a one-line reason.

A JavaScript wrapper might look like this:

async function moderate(text) {
  const res = await fetch("https://api.subtoapi.app/v1/messages", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "claude-opus-4-5-20251101",
      max_tokens: 200,
      system: MODERATION_SYSTEM_PROMPT,
      messages: [{ role: "user", content: `Classify this message: "${text}"` }]
    })
  });

  const data = await res.json();
  const raw = data.content[0].text;
  return JSON.parse(raw);
}

Always wrap the JSON.parse in a try/catch — even with a strict schema, models occasionally add stray text. If parsing fails, treat the content as flagged for manual review rather than silently passing it through.

Handling Edge Cases

A few patterns matter in production:

Latency and Cost Considerations

Running every message through a full Claude call adds real latency and cost at scale. Common mitigations:

If you're already routing production traffic through SubToAPI, the same API key and endpoint you use for user-facing generation can run your moderation calls — no separate billing relationship, and usage for both is visible in one dashboard. Streaming isn't necessary for moderation calls, but the Messages API docs cover the request format you'd reuse, and tool use is worth considering if you want the model to call a lookup function (e.g., checking a blocklist) as part of its verdict.

Wiring It Into Your Pipeline

A typical flow:

  1. User submits content.
  2. Fast local filter (regex, denylist) runs first.
  3. If it passes, send to Claude moderation classifier.
  4. Parse the structured verdict.
  5. Route based on severity: allow, soft-flag for review, or hard-block with a user-facing message.
  6. Log all flagged content with the model's reason for audit and policy tuning.

Start with a small, explicit category list and expand it as you see real false positives and false negatives — moderation policy is rarely right on the first attempt, and the structured JSON output makes it easy to review logs and tighten the system prompt over time.

FAQ

Does Claude have a built-in moderation endpoint like other providers? No. Claude moderation is implemented by prompting the Messages API with a classification system prompt and parsing structured JSON output — there's no separate moderation-only endpoint.

Can Claude moderation replace a keyword filter entirely? Not for high-volume systems. Use a fast keyword/regex layer first to catch obvious cases cheaply, and reserve Claude calls for ambiguous or context-dependent content where nuance matters.

How do I avoid inconsistent moderation verdicts? Use a narrow, explicit system prompt with a fixed JSON schema, low max_tokens, and fixed category names. Log outputs regularly and refine the prompt based on real misclassifications rather than guessing upfront.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →