Azure Content Moderator Alternative — Profanity Filter
Pricing
from $1.00 / 1,000 text screeneds
Azure Content Moderator Alternative — Profanity Filter
Azure Content Moderator alternative and drop-in profanity filter + PII detector for the text screen API. Accepts POST /contentmoderator/moderate/v1.0/ProcessText/Screen and returns the same Terms, PII, Classification and Status JSON. Content Safety is a different API. $1 per 1,000 texts.
Pricing
from $1.00 / 1,000 text screeneds
Rating
0.0
(0)
Developer
drop-in apis
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 hours ago
Last modified
Categories
Share
Azure Content Moderator Alternative — Profanity Filter & PII Detector
Azure Content Moderator alternative, drop-in profanity filter and PII detector for text: this Actor accepts POST /contentmoderator/moderate/v1.0/ProcessText/Screen and returns the same Terms, PII, Classification and Status JSON. Microsoft retires Content Moderator on 15 March 2027 (overview; the lifecycle page says 1 April 2027).
At a glance: $1.00 per 1,000 screened texts (failed requests are not charged) · about 20–80 ms per screen on a warm Standby instance · up to 1,024 characters per text · text only (no image or video moderation). Try it with no code: click Start with the prefilled input (batch mode), or send one request to the Standby endpoint.
Last updated: 2026-10-02 · Full migration guide: https://alidaram99.github.io/api-alternatives/azure-content-moderator-alternative/
Microsoft's successor, Azure AI Content Safety, uses a different URL, auth and JSON (severity levels instead of Terms, PII and Category1/2/3). With this Actor you point your existing code at a new endpoint and keep everything else.
- ✅ Same route, query parameters (
language,classify,PII,autocorrect,listId) and body formats (text/plain,text/html,text/xml,text/markdown) - ✅ Same response field names, casing and order.
Terms: nullwhen nothing is found, like Azure - ✅ Built-in profanity list in 24 languages, with correct
Index/OriginalIndexoffsets - ✅ PII detection: email, IPv4/IPv6, US/UK phone, US SSN, US street address
- ✅ English classification (Category1/2/3 plus ReviewRecommended), as in Azure
- ✅ $1 per 1,000 screens; errors are free
- 🔒 Nothing is stored or logged. Text is screened in memory inside the Actor and no third-party AI API is called.
Migrate in one minute
Your endpoint is the Actor's Standby URL. You'll find it on the Actor's Standby tab, for example https://<username>--content-moderator-compat.apify.actor. Authenticate with your Apify API token, either as ?token=… or as Authorization: Bearer …. The Ocp-Apim-Subscription-Key header is accepted and ignored.
curl / any REST client
# Beforecurl -X POST "https://westus.api.cognitive.microsoft.com/contentmoderator/moderate/v1.0/ProcessText/Screen?language=eng&classify=True&PII=True" \-H "Ocp-Apim-Subscription-Key: $AZURE_KEY" -H "Content-Type: text/plain" \--data-binary 'Is this a crap email abcdef@abcd.com, phone: 6657789887, IP: 255.255.255.255, 1 Microsoft Way, Redmond, WA 98052'# After: same path, query and bodycurl -s -X POST "https://<username>--content-moderator-compat.apify.actor/contentmoderator/moderate/v1.0/ProcessText/Screen?language=eng&classify=True&PII=True&token=$APIFY_TOKEN" \-H 'Content-Type: text/plain' \--data-binary 'Is this a crap email abcdef@abcd.com, phone: 6657789887, IP: 255.255.255.255, 1 Microsoft Way, Redmond, WA 98052'
C# (HttpClient, .NET 6+)
using System.Net.Http.Headers;using System.Text;using System.Text.Json;var baseUrl = "https://<username>--content-moderator-compat.apify.actor";var token = Environment.GetEnvironmentVariable("APIFY_TOKEN")!;using var http = new HttpClient();http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);var content = new StringContent("Is this a crap email abcdef@abcd.com?", Encoding.UTF8, "text/plain");var response = await http.PostAsync($"{baseUrl}/contentmoderator/moderate/v1.0/ProcessText/Screen?language=eng&classify=True&PII=True", content);response.EnsureSuccessStatusCode();using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());var root = json.RootElement;Console.WriteLine($"Status {root.GetProperty("Status").GetProperty("Code").GetInt32()}, " +$"Category3 {root.GetProperty("Classification").GetProperty("Category3").GetProperty("Score").GetDouble():F3}, " +$"first term '{root.GetProperty("Terms")[0].GetProperty("Term").GetString()}'");// Status 3000, Category3 0.971, first term 'crap'
If you use the old Microsoft.Azure.CognitiveServices.ContentModerator SDK, set client.Endpoint to the Standby URL and pass ServiceClientCredentials that add the Authorization: Bearer header. That SDK path has not been tested; the HttpClient code above has.
Python (requests)
import osimport requestsBASE = "https://<username>--content-moderator-compat.apify.actor"APIFY_TOKEN = os.environ["APIFY_TOKEN"]r = requests.post(f"{BASE}/contentmoderator/moderate/v1.0/ProcessText/Screen",params={"language": "eng", "classify": "True", "PII": "True"},headers={"Content-Type": "text/plain", "Authorization": f"Bearer {APIFY_TOKEN}"},data="This is crap, email me at someone@example.com".encode("utf-8"),)screen = r.json()print(screen["Status"]["Code"], screen["Classification"]["Category3"]["Score"],[t["Term"] for t in screen["Terms"] or []], [e["Text"] for e in screen["PII"]["Email"]])# 3000 0.98 ['crap'] ['someone@example.com']
If you use the azure-cognitiveservices-vision-contentmoderator SDK, pass msrest.authentication.BasicTokenAuthentication({"access_token": APIFY_TOKEN}) as the credentials and set endpoint to the Standby URL. (That SDK path has not been tested; the requests code above has.)
Node.js
const BASE = 'https://<username>--content-moderator-compat.apify.actor';const res = await fetch(`${BASE}/contentmoderator/moderate/v1.0/ProcessText/Screen?language=eng&classify=True`, {method: 'POST',headers: { 'Content-Type': 'text/plain', Authorization: `Bearer ${process.env.APIFY_TOKEN}` },body: 'You are a worthless idiot',});const screen = await res.json();console.log(screen.Status.Code, screen.Classification.ReviewRecommended, screen.Classification.Category3.Score);// 3000 true 0.997
Response example (real output)
{"OriginalText": "Is this a crap email abcdef@abcd.com, phone: 6657789887, IP: 255.255.255.255, 1 Microsoft Way, Redmond, WA 98052","NormalizedText": "Is this a crap email abcdef@ abcd. com, phone: 6657789887, IP: 255. 255. 255. 255, 1 Microsoft Way, Redmond, WA 98052","Misrepresentation": null,"PII": {"Email": [{ "Detected": "abcdef@abcd.com", "SubType": "Regular", "Text": "abcdef@abcd.com", "Index": 21 }],"SSN": [],"IPA": [{ "SubType": "IPV4", "Text": "255.255.255.255", "Index": 61 }],"Phone": [{ "CountryCode": "US", "Text": "6657789887", "Index": 45 }],"Address": [{ "Text": "1 Microsoft Way, Redmond, WA 98052", "Index": 78 }]},"Classification": {"ReviewRecommended": true,"Category1": { "Score": 0.0023 },"Category2": { "Score": 0.2708 },"Category3": { "Score": 0.9562 }},"Language": "eng","Terms": [{ "Index": 10, "OriginalIndex": 10, "ListId": 0, "Term": "crap" }],"Status": { "Code": 3000, "Description": "OK", "Exception": null },"TrackingId": "c110a5a9-3659-4fff-b2ce-fcac1f4ae9a9"}
This is Microsoft's own documented example sentence. NormalizedText, the Terms offsets and every PII index are identical to Microsoft's published response.
Compatibility matrix
| Feature | Status |
|---|---|
| Route, HTTP method, query parameters (case-insensitive), content types, 1,024-character limit | Identical |
Response field names, casing, order, Status, Misrepresentation: null, Terms: null when clean, TrackingId | Identical |
NormalizedText (space inserted after punctuation, as Azure does) | Identical on Microsoft's documented examples; may differ on unusual inputs |
Terms with Index (into NormalizedText) and OriginalIndex (into OriginalText), ListId: 0 | Same format. The word list is our own, so matches can differ from Azure's private list |
PII (Email, IPA, Phone, Address, SSN) with Azure's sub-field names | Same format. Patterns are deliberately strict: phones are US/UK, addresses US with state and ZIP, SSNs valid ddd-dd-dddd only |
Classification Category1 (sexually explicit), Category3 (offensive) | Approximate. Open model, different scores from Azure's |
Classification Category2 (sexually suggestive) | Approximate proxy: max(Category1, 0.3 × obscene). Flirty but clean text is not detected |
ReviewRecommended | True when any category is ≥ 0.5. Azure's internal thresholds are not published |
| Classification for non-English text | Omitted, as in Azure (English only) |
autocorrect=true | Accepted. AutoCorrectedText is returned but no spelling correction is applied (same as NormalizedText) |
listId (custom term lists) | Not supported. Custom lists live in your Azure resource. The built-in list is applied, and the response carries an X-Compat-Warning header |
| Image and video moderation, term/image list management, the human review tool | Not supported (text screening only) |
How it compares
| Option | Same ProcessText/Screen request and JSON? | Price | Notes |
|---|---|---|---|
| This Actor | Yes: change the endpoint, add an Apify token | $1 per 1,000 texts | Category scores approximate; custom term lists (listId) not supported |
| Azure Content Moderator | It is the original | Azure pricing | Retires 15 Mar 2027 |
| Azure AI Content Safety | No: different request and JSON (severity levels per harm category) | Azure pricing | Microsoft's recommended successor; rewrite and re-tune |
| Standalone profanity or PII APIs | No | Varies | Cover only part of the Screen response |
Pricing
$1.00 per 1,000 screened texts (pay-per-event text-screened). Requests that fail validation (empty, too long, wrong content type) are not charged. Apify also adds its standard small per-start fee to each run, and you don't pay for idle time in Standby mode. Set a maximum total charge per run; once it is reached the API returns 429 {"Error":{"Code":"TooManyRequests",…}}.
Batch mode (no code)
Run the Actor normally with a list of texts and get one dataset row per text. Each row has the category scores, terms and PII, plus the full Content Moderator response. You can export it as CSV, Excel or JSON.
{ "texts": ["Thanks for your order, it ships tomorrow.", "This is crap, you idiot. Email me at someone@example.com"], "PII": true }
How scores are computed
- Category1 = Detoxify
sexual_explicit. - Category3 = the maximum of
toxicity,obscene,insult,threatandidentity_attack. - Category2 =
max(Category1, 0.3 × obscene).
Detoxify is Apache-2.0 Detoxify (unbiased-toxic-roberta, quantized ONNX, running on CPU inside the Actor). Clear-cut offensive text scores 0.95–0.99 on Category3, and benign text scores below 0.01. Scores are not identical to Azure's. If you rely on precise thresholds, re-check them on a sample of your own texts with batch mode before switching traffic.
Language is auto-detected and returned as an ISO 639-3 code. Latin-script text shorter than 40 characters is treated as English. For short non-English texts, pass language=spa, language=deu and so on so that the right profanity list is used.
Latency
On a warm instance, a screen takes about 20–80 ms and the instance handles about 15+ requests/s. After about 5 minutes without requests the instance sleeps, and the next request waits a few seconds while it starts.
Limits
- Text only: image and video moderation, term/image list management and the human review tool are not supported.
- Up to 1,024 characters per text, as in Azure's own Screen API; longer text returns HTTP 400.
- Custom term lists (
listId) are not supported; the built-in term list is applied and the response carries anX-Compat-Warningheader. - Category scores are independent Detoxify estimates, not identical to Azure's; re-check any threshold on a sample of your own texts (batch mode makes that easy) before switching traffic.
- After about 5 minutes without requests the Standby instance sleeps, and the next request waits a few seconds while it starts.
FAQ
What replaces Azure Content Moderator without rewriting my code?
This endpoint. It takes the same ProcessText/Screen path, query parameters and raw-text body, and returns the same JSON. $1 per 1,000 successful screens.
Is this a profanity filter?
Yes, among other things. The built-in Terms list covers profanity in 24 languages (the same categories Azure Content Moderator shipped), with the correct Index/OriginalIndex character offsets so you can redact in place. Pass classify=True/PII=True too for the Category1/2/3 classification and PII detection in the same call.
When does Azure Content Moderator retire?
15 March 2027 according to Microsoft's product overview; the lifecycle page says 1 April 2027. Plan for 15 March.
Is Azure AI Content Safety a drop-in replacement?
No. It uses different fields (severity levels for Hate, Sexual, SelfHarm and Violence) and a different request. Use it if you can change your parser and re-tune; use this Actor if you can't yet.
Does it detect email, phone and address (PII)?
Yes. PII follows the Content Moderator shape: Email, IPA (IPv4/IPv6), Phone (US/UK), Address (US with state and ZIP) and SSN. Patterns are deliberately strict.
Are Category1, Category2 and Category3 the same numbers as Azure?
They are the same fields, computed by an open model. Category2 (suggestive) is a documented proxy. ReviewRecommended is true when any category is ≥ 0.5. Re-check thresholds on your own texts.
Are custom term lists (listId) supported?
No. Custom lists live inside your Azure resource. The built-in list (ListId 0) is always applied, and the response carries an X-Compat-Warning header when you pass a custom listId.
What does a ProcessText/Screen call cost?
$0.001 per screened text ($1 per 1,000). Requests that fail validation are not charged.
Is my text stored?
No. Nothing is written to disk or logged; text is screened in memory and discarded.
What about short non-English texts?
Latin-script text under 40 characters is treated as English. Pass language=spa, language=deu and so on to use the right profanity list.
Is this affiliated with Microsoft?
No. It is an independent, compatible implementation of the public Content Moderator v1.0 text screening interface.