Profanity filtering users can't bypass.
Copy a blank character for a name or a message, or paste text to find the ones hiding in it.
Each with its code point, the way to write it in HTML and a button that copies it.
| Character | Code point | HTML | What it does | Copy |
|---|---|---|---|---|
| Zero-width characters No width at all: the ones people mean by an invisible character. | ||||
| Zero width space ZWSP | U+200B | ​ | No width at all. The usual way to split a word a filter is looking for. | |
| Zero width non-joiner ZWNJ | U+200C | ‌ | Keeps two letters from joining. Persian and several Indian scripts need it. | |
| Zero width joiner ZWJ | U+200D | ‍ | Joins emoji into one, as in 👩💻, and letters in some scripts. | |
| Word joiner WJ | U+2060 | ⁠ | A zero width space that also forbids a line break. | |
| Zero width no-break space BOM | U+FEFF |  | The byte order mark. At the start of a file it is metadata; anywhere else it hides. | |
| Blank letters Drawn as an empty letter. Games and chat apps that refuse a blank name often take these. | ||||
| Hangul filler | U+3164 | ㅤ | A blank Korean letter. The usual blank name in games and chat. | |
| Hangul choseong filler | U+115F | ᅟ | A blank Korean initial consonant. | |
| Hangul jungseong filler | U+1160 | ᅠ | A blank Korean vowel. | |
| Halfwidth Hangul filler | U+FFA0 | ᅠ | The half-width blank Korean letter. | |
| Braille pattern blank | U+2800 | ⠀ | A braille cell with no dots: a blank that counts as a letter. | |
| Format characters Formatting with nothing to draw, most of them deprecated. | ||||
| Soft hyphen SHY | U+00AD | ­ | Shows a hyphen only where a line breaks; invisible mid-line. | |
| Combining grapheme joiner CGJ | U+034F | ͏ | A combining mark that draws nothing. | |
| Mongolian vowel separator MVS | U+180E | ᠎ | A space until Unicode 6.3; now it draws nothing. | |
| Khmer vowel inherent aq | U+17B4 | ឴ | A Khmer vowel Unicode deprecated; it draws nothing. | |
| Khmer vowel inherent aa | U+17B5 | ឵ | A Khmer vowel Unicode deprecated; it draws nothing. | |
| Function application | U+2061 | ⁡ | An invisible maths operator. | |
| Invisible times | U+2062 | ⁢ | An invisible maths operator. | |
| Invisible separator | U+2063 | ⁣ | An invisible maths comma. | |
| Invisible plus | U+2064 | ⁤ | An invisible maths operator. | |
| Inhibit symmetric swapping | U+206A |  | A deprecated shaping control; it draws nothing. | |
| Activate symmetric swapping | U+206B |  | A deprecated shaping control; it draws nothing. | |
| Inhibit Arabic form shaping | U+206C |  | A deprecated shaping control; it draws nothing. | |
| Activate Arabic form shaping | U+206D |  | A deprecated shaping control; it draws nothing. | |
| National digit shapes | U+206E |  | A deprecated shaping control; it draws nothing. | |
| Nominal digit shapes | U+206F |  | A deprecated shaping control; it draws nothing. | |
| Direction controls They set which way text runs. | ||||
| Left-to-right mark LRM | U+200E | ‎ | Sets the direction of the text around it. Invisible. | |
| Right-to-left mark RLM | U+200F | ‏ | Sets the direction of the text around it. Invisible. | |
| Arabic letter mark ALM | U+061C | ؜ | A right-to-left mark for Arabic text. | |
| Left-to-right embedding LRE | U+202A | ‪ | Starts a run of left-to-right text. | |
| Right-to-left embedding RLE | U+202B | ‫ | Starts a run of right-to-left text. | |
| Pop directional formatting PDF | U+202C | ‬ | Ends an embedding or an override. | |
| Left-to-right override LRO | U+202D | ‭ | Forces the text after it left to right. | |
| Right-to-left override RLO | U+202E | ‮ | Shows the text after it backwards: "gpj.exe" reads as "exe.jpg". | |
| Left-to-right isolate LRI | U+2066 | ⁦ | Starts an isolated left-to-right run. | |
| Right-to-left isolate RLI | U+2067 | ⁧ | Starts an isolated right-to-left run. | |
| First strong isolate FSI | U+2068 | ⁨ | Starts a run in the direction of its first letter. | |
| Pop directional isolate PDI | U+2069 | ⁩ | Ends an isolate. | |
| Odd spaces They look like a space and are not one, so a search or a split misses them. | ||||
| No-break space NBSP | U+00A0 |   | Looks like a space, but a word on either side never splits. | |
| En quad | U+2000 |   | A space half an em wide. | |
| Em quad | U+2001 |   | A space an em wide. | |
| En space | U+2002 |   | A space half an em wide. | |
| Em space | U+2003 |   | A space an em wide. | |
| Three-per-em space | U+2004 |   | A third of an em. | |
| Four-per-em space | U+2005 |   | A quarter of an em. | |
| Six-per-em space | U+2006 |   | A sixth of an em. | |
| Figure space | U+2007 |   | The width of a digit. | |
| Punctuation space | U+2008 |   | The width of a full stop. | |
| Thin space | U+2009 |   | A narrow space. | |
| Hair space | U+200A |   | The narrowest space. | |
| Narrow no-break space NNBSP | U+202F |   | A thin space that never breaks. | |
| Medium mathematical space MMSP | U+205F |   | A space for formulas. | |
| Ideographic space | U+3000 |   | A space as wide as a Chinese character. | |
| Line separator | U+2028 | 
 | A line break some apps honor and some ignore. | |
| Paragraph separator | U+2029 | 
 | A paragraph break some apps honor and some ignore. | |
Unprofane takes each one out, or reads it as its Latin letter, before it reads the words.
Caught, by trick: the Scunthorpe Test, rules alone, 2026-10-20
Every check reads through them before it reads the words, and tells you which trick it found.
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":"nice game, f\u200buck you","context":"chat"}'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": "nice game, f\u200buck you",
"context": "chat"
}),
});
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": "nice game, f\u200buck you",
"context": "chat",
},
timeout=5.0,
)
result = r.json()req, _ := http.NewRequest("POST", "https://api.unprofane.com/v1/check",
strings.NewReader(`{"text":"nice game, f\u200buck you","context":"chat"}`))
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":"nice game, f\u200buck you","context":"chat"}',
]]));
$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":"nice game, f\u200buck you","context":"chat"}'
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\":\"nice game, f\u200buck you\",\"context\":\"chat\"}", 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\":\"nice game, f\u200buck you\",\"context\":\"chat\"}"){
"allowed": false,
"action": "block",
"evasion": [
"zero_width"
],
"matches": [
{
"text": "f\u200buck you",
"normalized": "fuck you",
"evasion": [
"zero_width"
]
}
],
"censored": "nice game, *********"
}