# Content Moderation API — Perspective API Alternative (`red.cars/content-moderation-scorer`) Actor

Content moderation API scoring text 0-1 across toxicity, hate, harassment, sexual, violence, self-harm and spam with custom policy rules and explainable reasons. Rules-first pricing: $0.008 per scored text, success-only billing. Perspective API alternative before its Dec 2026 sunset.

- **URL**: https://apify.com/red.cars/content-moderation-scorer.md
- **Developed by:** [AutomateLab](https://apify.com/red.cars) (community)
- **Categories:** AI, Developer tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 text scoreds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Content Moderation API for user-generated text — scores comments, reviews, posts, and support tickets 0-1 across **7 policy categories** (toxicity, hate, harassment, sexual, violence, self-harm, spam) with **explainable plain-language reasons** and **custom policy rules** your team defines. A drop-in **Google Perspective API alternative** for platforms migrating before its December 2026 sunset. Deterministic rules decide clear cases at zero AI cost; an AI judgment layer scores only the ambiguous middle band. **$0.008 per scored text, success-only billing — malformed items and processing failures are never charged.**

### What does content-moderation-scorer do?

It takes a batch of user-generated texts — YouTube comments, product reviews, forum posts, support tickets, chat messages — and returns a moderation verdict per text: a `safe` boolean, an `overallScore` from 0 to 1, per-category scores, the flagged categories, a **plain-language reason** a human moderator can act on, and `customFlags` for your own house rules (block competitor mentions, medical advice, scam links — anything OpenAI's free Moderation endpoint cannot express because its taxonomy is fixed). You can download the results in JSON, CSV, Excel, or HTML.

Unlike a profanity checker, this is a **custom content moderation policy engine**: you supply your own rules and examples, the scorer enforces them alongside the 7 standard categories, and ambiguous texts are escalated to an AI policy judgment rather than guessed.

### Why use content-moderation-scorer?

- **Custom policy support** — express house rules the free fixed-taxonomy endpoints can't: flag competitor mentions, medical advice, scam links, off-topic promotion.
- **Explainable verdicts** — every record carries a reason listing the exact signals matched, plus `decidedBy: rules|jev` so you know how each decision was made.
- **Perspective API migration path** — Google's Perspective API shuts down Dec 31 2026; this actor covers its core toxicity/abuse scoring with plain-JSON input/output you can map 1:1.
- **Spam & scam detection included** — link spam, scam phrases ("double your money", "crypto giveaway"), shouting, repeated-character spam: the patterns profanity checkers miss.
- **Cost control** — deterministic rules decide clear cases free; only texts scoring in the 0.3-0.7 ambiguity band consume AI judgment, and the AI call cost is baked into your event price.
- **API-ready** — runs with Apify standby mode: keep a container warm and POST texts for low-latency scoring, or run batches of up to 1,000 texts per run. Integrate via Apify API, webhooks, n8n, Zapier, Make, or LangChain/CrewAI agents.

### How to use content-moderation-scorer

1. Click **Try for free** — no subscription needed.
2. Paste your texts into the `texts` field (plain strings, or `{"text": "...", "id": "your-id"}` objects to keep your own identifiers).
3. Optionally set a `policy`: a subset of the 7 categories to enforce, and `customRules` like `{"name": "no_competitor_mentions", "description": "flag rival brand mentions", "examples": ["Acme Corp"]}`.
4. Set `threshold` (default 0.7) and `maxTexts` if you want cost caps.
5. Run. Each scored text appears in the dataset with its verdict; download as JSON/CSV/Excel.

For API use: POST the same JSON input to a standby-instance URL and get verdicts back synchronously.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `texts` | array (required) | — | Texts to score: strings or `{text, id}` objects. 1-1000 per run. |
| `policy` | object | `{}` | `{categories: [...subset...], customRules: [{name, description, examples}]}` |
| `threshold` | number 0-1 | `0.7` | Flag threshold. |
| `maxTexts` | integer | `500` | Cap per run (cost control). |
| `useJevEscalation` | boolean | `true` | AI judgment for ambiguous texts (0.3-0.7 band, custom-rule matches). |

### Output

One dataset record per scored text (each is one billable event):

```json
{
  "textId": "review-42",
  "text": "unbelievable offer!!! ACT NOW and double your money risk-free",
  "safe": false,
  "overallScore": 0.8,
  "categories": {
    "toxicity": 0.0, "hate": 0.0, "harassment": 0.0, "sexual": 0.0,
    "violence": 0.0, "self_harm": 0.0, "spam": 0.8
  },
  "flagged": ["spam"],
  "reason": "spam: phrase 'double your money' (severity 0.8); excessive punctuation (severity 0.3)",
  "decidedBy": "rules",
  "customFlags": ["no_competitor_mentions"]
}
```

### Data table

| Field | Meaning |
|---|---|
| `textId` | Your id, or `text-N` |
| `text` | The scored text |
| `safe` | true when `overallScore` < threshold |
| `overallScore` | 0-1 policy-violation score |
| `categories` | The 7 category scores (toxicity, hate, harassment, sexual, violence, self\_harm, spam) |
| `flagged` | Categories at/above threshold |
| `reason` | Plain-language explanation with the exact matched signals |
| `decidedBy` | `rules` (deterministic, free) or `jev` (AI judgment layer) |
| `customFlags` | Your custom policy rules that matched |

### Pricing — how much does it cost to moderate text?

**$0.008 per scored text** (`text-scored` event). No subscription, no minimum.

- Charged: every text that receives a verdict — safe or flagged, rules-decided or AI-judged.
- **Not charged:** malformed input items, texts that fail processing, and empty input — pushed as free error records (success-only billing, the Apify first-party norm).
- A 500-comment batch = $4.00 worst case; cap spend per run with `maxTexts`.

### Tips and advanced options

- **Moderate YouTube comments, Reddit posts, or product reviews at scale**: pipe the output of a comments scraper (YouTube Comments Scraper, Reddit Scraper, Facebook Comments Scraper) straight into `texts`.
- **Tune recall vs precision** with `threshold`: 0.5 catches borderline content; 0.9 only near-certain violations.
- **House rules**: put your policy in `customRules`; matched texts escalate with the rule's description and examples for context-aware judgment.
- **Cost control**: `maxTexts` caps a run; `useJevEscalation: false` scores rules-only (zero AI ambiguity handling, fastest and cheapest behavior).

### FAQ, disclaimers, and support

**Is this a profanity checker?** No — profanity checkers race to $0.00025/event on word-lists. This is a policy scorer: contextual categories, custom rules, explainable reasons.

**What replaces the Google Perspective API?** Perspective sunsets Dec 31 2026. This actor maps its core use case (score UGC 0-1 for toxicity/abuse with reason codes) onto Apify's pay-per-event pricing, plus custom policy support Perspective never had.

**What if the AI judgment layer is unavailable?** Texts are decided by the deterministic rules layer and still charged — a delivered verdict is the product. Malformed items and processing failures are always free.

**Legality & content:** you are responsible for the texts you submit; the scorer returns analysis only. Feature requests: open an issue on the Issues tab — custom categories and policy packs are available on request.

***

*Keywords: content moderation API, toxicity scoring API, text moderation actor, custom content moderation policy, spam comment detection API, UGC moderation API, Perspective API alternative, moderate YouTube comments, moderate product reviews, moderate forum posts.*

# Actor input Schema

## `texts` (type: `array`):

User-generated texts to score: plain strings, or objects {"text": "...", "id": "your-id"} to keep your own identifiers. Each scored text is one billable event. 1-1000 per run.

## `policy` (type: `object`):

Optional. categories: subset of \[toxicity, hate, harassment, sexual, violence, self\_harm, spam] to enforce flagging on (all are still scored; default enforces all). customRules: \[{name, description, examples}] - your own policy, e.g. {"name": "no\_competitor\_mentions", "description": "flag mentions of rival brands", "examples": \["Acme Corp"]}. Texts matching a custom rule are escalated to the AI judgment layer with the rule's context and reported via customFlags.

## `threshold` (type: `number`):

Score at or above which a category/text is flagged. 0.0-1.0.

## `maxTexts` (type: `integer`):

Cap on how many texts one run processes (cost control).

## `useJevEscalation` (type: `boolean`):

Route ambiguous texts (rules score in the 0.3-0.7 band, or custom-rule matches) through an AI policy judgment. Clear cases (very safe / clearly violating) are always decided by rules at zero AI cost. Requires OPENROUTER\_API\_KEY env var on the actor; when unavailable, rules decide everything.

## Actor input object example

```json
{
  "texts": [
    "Great article, thanks for the detailed write-up!",
    "hey, you're an idiot for believing that - click here to buy now and get free money",
    "This product broke after two days, very disappointed",
    "unbelievable offer!!! ACT NOW and double your money risk-free at https://spam.example.com",
    {
      "text": "The restaurant was okay, service a bit slow but food was good",
      "id": "review-42"
    }
  ],
  "policy": {
    "categories": [
      "toxicity",
      "hate",
      "harassment",
      "sexual",
      "violence",
      "self_harm",
      "spam"
    ],
    "customRules": [
      {
        "name": "no_competitor_mentions",
        "description": "Flag comments promoting rival brands",
        "examples": [
          "acme",
          "contoso"
        ]
      }
    ]
  },
  "threshold": 0.7,
  "maxTexts": 500,
  "useJevEscalation": true
}
```

# Actor output Schema

## `results` (type: `string`):

One record per scored text: id, text, safe, overallScore (0-1), per-category scores (toxicity, hate, harassment, sexual, violence, self\_harm, spam), flagged categories, plain-language reason, decidedBy (rules|jev), customFlags. Downloadable as JSON, CSV, Excel, or HTML.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "texts": [
        "Great article, thanks for the detailed write-up!",
        "hey, you're an idiot for believing that - click here to buy now and get free money",
        "This product broke after two days, very disappointed",
        "unbelievable offer!!! ACT NOW and double your money risk-free at https://spam.example.com",
        {
            "text": "The restaurant was okay, service a bit slow but food was good",
            "id": "review-42"
        }
    ],
    "policy": {
        "categories": [
            "toxicity",
            "hate",
            "harassment",
            "sexual",
            "violence",
            "self_harm",
            "spam"
        ],
        "customRules": [
            {
                "name": "no_competitor_mentions",
                "description": "Flag comments promoting rival brands",
                "examples": [
                    "acme",
                    "contoso"
                ]
            }
        ]
    },
    "useJevEscalation": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("red.cars/content-moderation-scorer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "texts": [
        "Great article, thanks for the detailed write-up!",
        "hey, you're an idiot for believing that - click here to buy now and get free money",
        "This product broke after two days, very disappointed",
        "unbelievable offer!!! ACT NOW and double your money risk-free at https://spam.example.com",
        {
            "text": "The restaurant was okay, service a bit slow but food was good",
            "id": "review-42",
        },
    ],
    "policy": {
        "categories": [
            "toxicity",
            "hate",
            "harassment",
            "sexual",
            "violence",
            "self_harm",
            "spam",
        ],
        "customRules": [{
                "name": "no_competitor_mentions",
                "description": "Flag comments promoting rival brands",
                "examples": [
                    "acme",
                    "contoso",
                ],
            }],
    },
    "useJevEscalation": True,
}

# Run the Actor and wait for it to finish
run = client.actor("red.cars/content-moderation-scorer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "texts": [
    "Great article, thanks for the detailed write-up!",
    "hey, you'\''re an idiot for believing that - click here to buy now and get free money",
    "This product broke after two days, very disappointed",
    "unbelievable offer!!! ACT NOW and double your money risk-free at https://spam.example.com",
    {
      "text": "The restaurant was okay, service a bit slow but food was good",
      "id": "review-42"
    }
  ],
  "policy": {
    "categories": [
      "toxicity",
      "hate",
      "harassment",
      "sexual",
      "violence",
      "self_harm",
      "spam"
    ],
    "customRules": [
      {
        "name": "no_competitor_mentions",
        "description": "Flag comments promoting rival brands",
        "examples": [
          "acme",
          "contoso"
        ]
      }
    ]
  },
  "useJevEscalation": true
}' |
apify call red.cars/content-moderation-scorer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,red.cars/content-moderation-scorer"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/hCfnj5C03rIAOoKC5/builds/vIddiUrDtEkMNE3aO/openapi.json
