← Blog

How to Build a Claude-Powered Content Moderation System

2026-11-05 · 5 min read · SubToAPI Team

Building a Claude-powered content moderation system means using Claude's language understanding to classify, score, and flag user-generated content — text posts, comments, chat messages, or uploaded documents — against your platform's rules, then routing the results into an automated or human-reviewed workflow. Unlike keyword-based filters, Claude understands context, sarcasm, coded language, and intent, which makes it far more effective at catching policy violations that simple regex or blocklists miss.

The core pattern is simple: send the content to Claude with a clear moderation policy and a structured output format, parse the response, and act on it (allow, flag, block, or escalate). The hard parts are designing the policy prompt correctly, handling edge cases, keeping latency low, and making the system auditable. Below is a practical blueprint you can implement today.

Step 1: Define Your Moderation Categories

Before writing any code, write down exactly what you're moderating for. Vague categories produce vague results. Good categories are specific and actionable:

Each category should map to an action: allow, flag_for_review, or block. Don't ask Claude to decide actions implicitly — define the mapping yourself so your system stays predictable and auditable.

Step 2: Design the Prompt for Structured Output

Ask Claude to return JSON, not prose. This makes parsing deterministic and lets you build downstream logic without fragile string matching.

You are a content moderation classifier. Analyze the user-submitted
text below against these categories: harassment, hate_speech, sexual_content,
violence, spam, self_harm, illegal_activity.

For each category, return a boolean "flagged" and a confidence score
0-100. Also return an overall "severity" (none, low, medium, high) and
a one-sentence "reason".

Respond with JSON only, no other text, matching this schema:
{
  "categories": {
    "harassment": {"flagged": bool, "confidence": number},
    "hate_speech": {"flagged": bool, "confidence": number},
    "sexual_content": {"flagged": bool, "confidence": number},
    "violence": {"flagged": bool, "confidence": number},
    "spam": {"flagged": bool, "confidence": number},
    "self_harm": {"flagged": bool, "confidence": number},
    "illegal_activity": {"flagged": bool, "confidence": number}
  },
  "severity": "none" | "low" | "medium" | "high",
  "reason": "string"
}

Text to analyze:
"""
{{content}}
"""

Keep the system prompt stable and version it. Changing wording even slightly can shift classification behavior, so treat your moderation prompt like code — review changes, test them against a labeled sample set before deploying.

Step 3: Call the API and Parse the Response

Here's a working example using SubToAPI, which exposes Claude through a standard HTTPS API with an application key (sub_live_...), so you don't need to manage direct provider credentials for each environment.

async function moderateContent(text) {
  const response = 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-sonnet-4",
      max_tokens: 400,
      system: MODERATION_SYSTEM_PROMPT,
      messages: [
        { role: "user", content: `Text to analyze:\n"""\n${text}\n"""` }
      ]
    })
  });

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

Wrap the JSON.parse in a try/catch — occasionally a model will add a stray sentence despite instructions. If parsing fails, retry once with a stricter reminder ("Respond with JSON only") before falling back to manual review.

Step 4: Map Results to Actions

Translate the structured output into a decision your application can enforce:

function decideAction(result) {
  const { severity, categories } = result;

  if (severity === "high") return "block";
  if (severity === "medium") return "flag_for_review";

  const anyFlagged = Object.values(categories).some(c => c.flagged && c.confidence > 70);
  return anyFlagged ? "flag_for_review" : "allow";
}

Log every decision with the original content hash, the full Claude response, and the action taken. This audit trail is essential for appeals, compliance reviews, and improving your prompt over time.

Step 5: Handle Scale and Latency

Moderation often needs to happen inline (before a post appears) or asynchronously (after it's published, flagged content gets pulled). Design for both:

If you expect bursts in traffic, make sure your provider setup gives you headroom — check the pricing page for request limits per plan, and read the streaming docs if you want to show moderation status in near real time on a dashboard.

Step 6: Combine with Human Review for Edge Cases

Claude is strong at catching clear violations and context-dependent nuance, but borderline cases — satire, reclaimed slurs, clinical discussion of self-harm — benefit from human review. Route anything with medium severity or conflicting category signals to a review queue instead of auto-blocking. This keeps false-positive rates low and protects user trust.

Getting Started

If you're already prototyping with a Claude subscription, you can turn it into a proper API backend for your moderation pipeline without re-architecting your billing or key management. SubToAPI gives you sub_live_... application keys, usage metadata per key, and team seats so multiple services (web app, mobile app, admin tools) can each moderate content independently with their own rate limits and logs. Start with the quickstart, review the messages API reference, and sign up for a free trial at /signup.

FAQs

Does Claude replace a dedicated moderation API? It can for most text moderation use cases, especially where context and nuance matter. For image/video moderation or extremely high-volume simple keyword filtering, pair it with specialized tools.

How do I reduce false positives? Use confidence thresholds per category, route medium-confidence results to human review, and continuously test prompt changes against a labeled dataset before deploying them to production.

Can I moderate content in multiple languages? Yes, Claude handles multilingual input natively. Keep your system prompt in English but instruct Claude to analyze content in its original language and return the same structured JSON schema regardless of input language.

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 →