Text moderation with the evidence in every answer, its accuracy measured in public, and a first call in two minutes.
WebPurify is a moderation company: a profanity filter API, image and video moderation, and a human moderation service, sold to brands and platforms.
WebPurify is not on the benchmark, so it has no bar and this page makes no claim about its accuracy. When you compare, ask for toxic text caught at a stated false-alarm rate, on text nobody tuned on.
The private test set, 9,029 texts labelled blind, read once on 2026-09-28, engine 2026-09-29. How it was measured
The real engine, live. Type a disguised word and watch it read, named and judged; type an innocent one and watch it pass.
Every answer carries the same evidence through the API: the words, where they were, how they were disguised and a censored version.
01
The words, where they were, how they were disguised and a censored version, so you can show the person what to change.
username
xXsh1tXxshit
leetspeakreview ยท strong
Shown as xX****Xx
02
False positives on innocent words are counted and published, and re-run for every engine version.
0.0%
false positives on 1,447 innocent words and phrases, the Scunthorpe Test of 2026-10-12
03
A project can also be set so that no text ever reaches a model.
Nothing stored
Each promise is a test in the source. Privacy
When the job is text, Unprofane shows why in every answer and publishes how often it is right.
A test key is free, with a plan or without one. One request, in the language you use, and the answer carries the evidence.
curl -X POST https://api.unprofane.com/v1/check \
-H "Authorization: Bearer up_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"xXsh1tXx","context":"username","policy":"teen"}'const res = await fetch('https://api.unprofane.com/v1/check', {
method: 'POST',
headers: { Authorization: 'Bearer up_test_YOUR_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
"text": "xXsh1tXx",
"context": "username",
"policy": "teen"
}),
});
const result = await res.json();import httpx
r = httpx.request(
"POST",
"https://api.unprofane.com/v1/check",
headers={"Authorization": "Bearer up_test_YOUR_KEY"},
json={
"text": "xXsh1tXx",
"context": "username",
"policy": "teen",
},
timeout=5.0,
)
result = r.json()req, _ := http.NewRequest("POST", "https://api.unprofane.com/v1/check",
strings.NewReader(`{"text":"xXsh1tXx","context":"username","policy":"teen"}`))
req.Header.Set("Authorization", "Bearer up_test_YOUR_KEY")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)$res = file_get_contents('https://api.unprofane.com/v1/check', false, stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer up_test_YOUR_KEY\r\nContent-Type: application/json\r\n",
'content' => '{"text":"xXsh1tXx","context":"username","policy":"teen"}',
]]));
$result = json_decode($res, true);require 'net/http'; require 'json'
uri = URI('https://api.unprofane.com/v1/check')
req = Net::HTTP::Post.new(uri, 'Authorization' => 'Bearer up_test_YOUR_KEY', 'Content-Type' => 'application/json')
req.body = '{"text":"xXsh1tXx","context":"username","policy":"teen"}'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
result = JSON.parse(res.body)using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "up_test_YOUR_KEY");
var req = new HttpRequestMessage(HttpMethod.Post, "https://api.unprofane.com/v1/check");
req.Content = new StringContent("{\"text\":\"xXsh1tXx\",\"context\":\"username\",\"policy\":\"teen\"}", Encoding.UTF8, "application/json");
var res = await http.SendAsync(req);
var result = await res.Content.ReadFromJsonAsync<JsonElement>();var http := HTTPRequest.new()
add_child(http)
http.request_completed.connect(func(_r, _code, _h, body):
var result = JSON.parse_string(body.get_string_from_utf8())
print(result))
http.request("https://api.unprofane.com/v1/check",
PackedStringArray(["Authorization: Bearer up_test_YOUR_KEY", "Content-Type: application/json"]),
HTTPClient.METHOD_POST, "{\"text\":\"xXsh1tXx\",\"context\":\"username\",\"policy\":\"teen\"}")Free test keys, 100 checks a day, no card. Live from $9 a month. Every answer shows its evidence.