Profanity filtering users can't bypass.
It finds the insult inside a compound, reads ß, umlauts and leetspeak, and lets Schuhwichse through.
Schulhof schoolyard wichser wanker
schoolyard wanker Schulhof******* block · strong
Name your users' country too: pudern is read as Austria reads it (every word read by country).Each answer is the rules alone, the fast mode, checking a comment with language: "de". In balanced mode, the default, the model reads what the rules leave open.
Each spelling as typed, what the rules read in it, the tricks they named and their answer.
ß written ss
Scheisskerl
reads asscheisskerl
block · strong
ö written oe
Arschloecher
reads asarschloecher
block · strong
Digits for letters
Sch3i55kerl
reads asscheisskerl
leetspeakblock · strong
Spaced out
W i c h s e r
reads aswichser
separatorblock · strong
A Cyrillic і
Wіchser
reads aswichser
homoglyphmixed_scriptblock · strong
Letters repeated
Wiiiichser
reads aswichser
repeated_charsblock · strong
An umlaut added
Ärschloch
reads asarschloch
diacriticsblock · strong
A zero for an o
Arschl0ch
reads asarschloch
leetspeakblock · strong
Each word is ordinary in one sentence and an insult in the other.
Hurenkind
In typesetting
Das ist ein Hurenkind im Absatz.
That is a widow line in the paragraph.
allowAt someone
Du Hurenkind!
You son of a whore!
block · strongSchweinehund
About yourself
Mein innerer Schweinehund.
My lazy inner self.
allowAt someone
Du Schweinehund!
You swine!
block · moderateOpfer
In the news
Opfer der Flut.
Victims of the flood.
allowAt someone
Du Opfer!
You loser!
block · moderateA list matching inside words finds a rude string in each; the rules read the whole word.
A list matching inside words8 of 8blocked
Unprofane, rules alone8 of 8allow
The same German texts given to every system, and the open benchmark’s German items.
91.0%
Unprofane
Flagged 5.7% of clean German texts
42.7%
Perspective API
Flagged 3.8% of clean German texts
39.9%
OpenAI moderation
Flagged 8.1% of clean German texts
0.938F1 on the Scunthorpe Test’s 53 German items, rules aloneThe public split, run of , engine 2026-10-18. Every language’s score
Other APIs and German
Send language "de" and a bare word reads as German writes it. Every language is still read.
Get your API key100 checks a day, no card
curl -X POST https://api.unprofane.com/v1/check \
-H "Authorization: Bearer up_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Halt die Fresse, du Schulhofwichser!","context":"comment","language":"de"}'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": "Halt die Fresse, du Schulhofwichser!",
"context": "comment",
"language": "de"
}),
});
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": "Halt die Fresse, du Schulhofwichser!",
"context": "comment",
"language": "de",
},
timeout=5.0,
)
result = r.json()req, _ := http.NewRequest("POST", "https://api.unprofane.com/v1/check",
strings.NewReader(`{"text":"Halt die Fresse, du Schulhofwichser!","context":"comment","language":"de"}`))
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":"Halt die Fresse, du Schulhofwichser!","context":"comment","language":"de"}',
]]));
$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":"Halt die Fresse, du Schulhofwichser!","context":"comment","language":"de"}'
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\":\"Halt die Fresse, du Schulhofwichser!\",\"context\":\"comment\",\"language\":\"de\"}", 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\":\"Halt die Fresse, du Schulhofwichser!\",\"context\":\"comment\",\"language\":\"de\"}"){
"allowed": false,
"action": "block",
"severity": "strong",
"matches": [
{
"text": "Halt die Fresse",
"normalized": "halt die fresse",
"category": "insult",
"severity": "moderate"
},
{
"text": "wichser",
"normalized": "wichser",
"category": "insult",
"severity": "strong"
}
],
"censored": "***************, du Schulhof*******!",
"language": {
"detected": "de",
"confidence": 0.75
}
}Every language Unprofane covers is read on every call, German with its disguises included.
Get your API key