Profanity filtering users can't bypass.
It knows Brazil’s insults and Portugal’s, reads their disguises, and reads each word as your users’ country does.
rapariga
In Portugal"country": "PT"
És uma rapariga muito simpática.
You’re a very nice girl.
allowIn Brazil"country": "BR"
És uma rapariga muito simpática.
You’re a very nice whore.
block · moderateName the country your users are in and the same sentence reads as theirs reads it. Without one, the rules read the words around the word. The words read by country.Each answer is the rules alone, the fast mode, checking a comment with language: "pt". 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.
Digits for letters
f1lh0 d4 put4
reads asfilho da puta
leetspeakblock · strong
Zeros for o
arr0mbad0
reads asarrombado
leetspeakblock · strong
Dotted
v.a.d.i.a
reads asvadia
separatorblock · strong
A Cyrillic а
vаdia
reads asvadia
homoglyphmixed_scriptblock · strong
Letters repeated
filho da putaaaa
reads asfilho da puta
repeated_charsblock · strong
Tilde dropped
cuzao
reads ascuzao
block · strong
Spaced out
f d p
reads asfdp
separatorblock · strong
Fours and a zero
c4r4lh0
reads ascaralho
leetspeakreview · strong
One language, and a different set of insults on each side of the Atlantic.
A 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 Portuguese texts given to every system, and the open benchmark’s Portuguese items.
94.0%
Unprofane
Flagged 2.1% of clean Portuguese texts
69.4%
Perspective API
Flagged 6.4% of clean Portuguese texts
55.2%
OpenAI moderation
Flagged 4.3% of clean Portuguese texts
0.968F1 on the Scunthorpe Test’s 33 Portuguese items, rules aloneThe public split, run of , engine 2026-10-18. Every language’s score
Other APIs and Portuguese
Send language "pt" and a bare word reads as Portuguese 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":"Vai tomar no cu, seu arrombado!","context":"comment","language":"pt"}'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": "Vai tomar no cu, seu arrombado!",
"context": "comment",
"language": "pt"
}),
});
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": "Vai tomar no cu, seu arrombado!",
"context": "comment",
"language": "pt",
},
timeout=5.0,
)
result = r.json()req, _ := http.NewRequest("POST", "https://api.unprofane.com/v1/check",
strings.NewReader(`{"text":"Vai tomar no cu, seu arrombado!","context":"comment","language":"pt"}`))
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":"Vai tomar no cu, seu arrombado!","context":"comment","language":"pt"}',
]]));
$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":"Vai tomar no cu, seu arrombado!","context":"comment","language":"pt"}'
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\":\"Vai tomar no cu, seu arrombado!\",\"context\":\"comment\",\"language\":\"pt\"}", 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\":\"Vai tomar no cu, seu arrombado!\",\"context\":\"comment\",\"language\":\"pt\"}"){
"allowed": false,
"action": "block",
"severity": "strong",
"matches": [
{
"text": "Vai tomar no cu",
"normalized": "vai tomar no cu",
"category": "sexual",
"severity": "strong"
},
{
"text": "seu arrombado",
"normalized": "seu arrombado",
"category": "insult",
"severity": "strong"
}
],
"censored": "***************, *************!",
"language": {
"detected": "pt",
"confidence": 0.9
}
}Every language Unprofane covers is read on every call, Portuguese with its disguises included.
Get your API key