no-nepali-profanity
A small, dependency-free profanity matcher for English, Romanized (Latin) Nepali and Devanagari Nepali, plus the Hindi slang common in Nepal. Built for moderating user-written text — names, comments, reviews — on Nepali sites, where false positives on real names are more damaging than a missed swear.
Zero runtime dependencies. Python ≥ 3.9. A direct port of the no-nepali-profanity npm package, with the same word lists and matching rules.
Documentation: mukhxadnahunna.com/python
Install
pip install no-nepali-profanity
Usage
from no_nepali_profanity import contains_profanity, find_profanity, tokenize
# boolean check — fastest
contains_profanity("Great teacher!") # False
contains_profanity("muji") # True
contains_profanity("मुजीको कक्षा") # True (Devanagari + postposition)
# which words — returns normalised matches as they appeared
find_profanity("f.u.c.k this sh1t") # ["fuck", "shit"]
find_profanity("f u c k this") # ["fuck"]
find_profanity("Randip Thapa") # []
find_profanity("*ss teacher") # ["*ss"]
# debugging — see what the matcher actually splits into
tokenize("Great teacher!") # ["great", "teacher"]
API
| Function | Returns | Notes |
|---|---|---|
contains_profanity(text, options?) |
bool |
Yes/no from find_profanity. |
find_profanity(text, options?) |
list[str] |
Matching words normalised + lowercased (leet decoded, case-folded), deduplicated. Empty when clean. |
check(text, options?) |
ProfanityCheck |
Scans once; inspect the result and censor it without scanning again. |
find_profanity_matches(text, options?) |
list[ProfanityMatch] |
Every occurrence with its position in the original text, sorted by position. |
censor(text, options?) |
str |
The text with each match masked: "you muji" → "you ****". Options: mask (default "*"), replace(match). |
create_filter(options?) |
ProfanityFilter |
Builds the tables once for fixed options. |
tokenize(text) |
list[str] |
Raw tokens the matcher sees. Useful for debugging why a word is (or isn't) caught. |
lexicon |
module | Tagged entries (WORDS, STEMS, PHRASES), flat per-script lists (LATIN_WORDS, DEVANAGARI_WORDS…) and suffixes. |
Match positions (ProfanityMatch.start, end) are character (code point) indices, unlike the npm package which
uses UTF-16 code units.
Censoring
censor("you muji") # "you ****"
censor("F.U.C.K this Sh1t!") # "******* this ****!"
censor("you muji", {"mask": "#"}) # "you ####"
censor("you muji", {"replace": lambda m: "[censored]"}) # "you [censored]"
find_profanity_matches("you muji") # [ProfanityMatch(text="muji", normalized="muji", start=4, end=8)]
Check and censor in one pass:
result = check("you muji")
result.has_profanity # True
result.words # ["muji"]
result.censor() # "you ****"
Options
find_profanity("fuck muji मुजी", {"languages": ["romanized"]}) # ["muji"]
contains_profanity("you idiot", {"strictness": "lenient"}) # False
find_profanity("terms and conditions", {"strictness": "strict"}) # ["conditions"]
languages: any of"english","romanized","devanagari". Default: all three.strictness:"lenient"(severe words only),"standard"(default, adds milder insults likeidiot,murkha) or"strict"(adds the stemsrand,cond,kand,lund, which also hit words likeRandipandconditions).
What it catches
- Case and Unicode forms:
IDIOT, full-width letters. - Leetspeak:
sh1t,@ss(0 1 3 4 5 7 @ $). !foribetween letters:sh!t,b!tch. Sentence-finalGreat teacher!is left alone.*for a hidden letter:f*ck,sh*t, and markdown emphasis like*sh*t*still reads as the word.- Stretched letters:
fuuuuck, for words of 4+ letters. - Spelled-out letters:
f.u.c.k,f u c k. - Nepali postpositions and plurals glued on:
mujiko,randiharu,मुजीको,…हरू. - Devanagari spelling variants: nukta, chandrabindu vs anusvara, zero-width joiners.
- Stems where no ordinary word starts the same way:
fucking,bitches,machiknee. - Multi-word phrases:
chaak ko pwal,pesa garne,sasto manche(Latin and Devanagari).
What it deliberately doesn't
- Short words match exactly, so
as,class,assignmentandAssamare fine. - Name collisions:
shitis a whole word only, because Shitij / शितिज is a name. Names like मुजी-adjacent Randip / राण्डीप, Putali / पुतली, Asha / आशा are checked in the test suite. - No caste names, surnames or ordinary words that are only offensive in context (e.g. kami, kukur). A word list can't tell a slur from someone's name; that needs human moderation.
- No judgement of context, sarcasm or meaning. This is a first-pass filter, not a moderator.
Development
python -m venv .venv && .venv/bin/pip install -e ".[test]"
.venv/bin/pytest
The word lists live in src/no_nepali_profanity/lexicon.py, apart from the matching logic in
src/no_nepali_profanity/core.py. Native-speaker review of the Nepali lists is the most valuable contribution.
License
MIT
Release files for no-nepali-profanity 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| no_nepali_profanity-0.1.0.tar.gz | 17.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| no_nepali_profanity-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.5 kB
Release files / no_nepali_profanity-0.1.0.tar.gz
| Download URL | no_nepali_profanity-0.1.0.tar.gz |
|---|---|
| Size | 17.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dd97cabd084852b33a2673dfdaeb890c5e35c06b3a334c7f3cd0f10cf9003f72
|
|
BLAKE2b-256 checksum How to use checksums |
4b356c07689f21a83c3315773a7f8a78110726039d5ff5ae91bcdfeeffcdabd2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / no_nepali_profanity-0.1.0-py3-none-any.whl
| Download URL | no_nepali_profanity-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7bf7b499d6583749f7fbd1c8361ab67906b1683ea752076225a96a42a19d7a5e
|
|
BLAKE2b-256 checksum How to use checksums |
b612f00f87b96b1e30a3afe0428ca0adf24922cbb259c5b71e468be8b918650d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log