Profanex — fast profanity detection and filtering for Python
Profanex is a Rust-powered Python profanity filter for detecting, locating, and masking bad words and phrases. It provides Unicode-safe spans, allowlists, optional fuzzy matching, configurable word lists, and parallel batch processing.
Installation · Quick start · Configuration · Documentation · Benchmarks
Why Profanex?
- A Rust-powered Aho-Corasick fast path for exact and multi-word phrase matching
- Unicode-safe Python string spans and consistent
contains,find, andcleanresults - Categories, allowlists, and custom YAML lexicons for application-specific moderation policies
- Optional fuzzy and evasion matching when recall matters more than raw throughput
- Ordered batch and iterator APIs with optional parallel processing
Defaults are conservative: all categories are enabled, word boundaries are enforced, and fuzzy and aggressive normalization are disabled.
Requirements
- Python 3.11 or newer
- A supported abi3 prebuilt wheel (one wheel covers 3.11+), or Rust 1.85.0 and maturin when building from source
Installation
uv add profanex
# or: python -m pip install profanex
For local development, see CONTRIBUTING.md.
Quick start
from profanex import Filter
f = Filter()
text = "You are a b1tch!"
print(f.contains(text)) # True
print(f.find(text))
print(f.clean(text)) # You are a *****!
print(f.analyze(text)) # (True, "You are a *****!") from one scan
Every match uses a half-open Python string span. Each Match also carries the lexicon term, categories, match kind (exact / phrase / fuzzy), and fuzzy score (100 for exact and phrase matches):
match = f.find(text)[0]
assert match.text == text[match.start:match.end]
assert match.term and match.categories
Filter.from_defaults() is equivalent to Filter() / Filter(FilterConfig()).
Configuration
from profanex import Category, Filter, FilterConfig
config = FilterConfig(
categories=frozenset(category for category in Category if category != Category.SLURS),
extra_banned={"project-specific-term"},
extra_allowlist=["projectcodename"],
enable_fuzzy=True,
threshold=85,
mask="stars",
)
f = Filter(config)
| Option | Default | Purpose |
|---|---|---|
categories |
all | Select enabled categories |
banned / banned_path |
packaged lexicon | Replace the banned lexicon |
extra_banned / extra_banned_path |
none | Add banned terms |
allowlist / allowlist_path |
packaged allowlist | Replace the allowlist |
extra_allowlist / extra_allowlist_path |
none | Add allowed terms |
word_boundaries |
True |
Require Unicode word boundaries |
normalize_leet |
True |
Apply the default leetspeak map |
normalize_repeated_chars |
False |
Match repeated characters such as fuuuck |
normalize_separated_runs |
False |
Match separated characters such as f.u.c.k / f u c k |
enable_fuzzy |
False |
Match similar single-token terms |
threshold |
85 |
Set the fuzzy score cutoff from 0 to 100 |
min_fuzzy_len |
4 |
Ignore fuzzy tokens/terms shorter than this |
fuzzy_length_delta |
2 |
Compare fuzzy terms within ±δ characters (maximum 64) |
fuzzy_max_token_len |
64 |
Skip fuzzy tokens longer than this (maximum 256) |
mask |
"stars" |
Use "stars", "vowels" (ASCII vowels only), or a serial Python callback |
banned and banned_path cannot be used together; the same applies to allowlist and allowlist_path. Allowlist entries have final precedence after normalization, so an explicit allowed term can disable a packaged or custom banned term.
Default leet covers digit/@/$ substitutions and infix !→i when the token contains an ASCII alphabetic anchor (for example b1tch, a55, sh!t). Numeric-only tokens such as 455 and 80085 are left unchanged even beside non-Latin text, and trailing ! is unchanged. Common asterisk masks (f*ck, sh*t) are packaged lexicon literals. For stronger evasion (fuuuck, f.u.c.k), opt in:
f = Filter(FilterConfig(
normalize_repeated_chars=True,
normalize_separated_runs=True,
))
Keep enable_fuzzy=True separate and measure it; it is off by default. For recipes, false-positive tradeoffs, and performance implications, see the configuration guide.
Custom YAML may be a flat list or a category mapping:
general:
- dang
sexual:
- example-term
Batch processing
Batch methods preserve input order. Parallel processing is opt-in:
texts = ["clean", "what the fuck", "please pass"]
flags = f.contains_many(texts)
matches = f.find_many(texts)
cleaned = f.clean_many(texts, parallel=True, workers=4)
flags, cleaned = f.analyze_many(texts, parallel=True, workers=4)
# Streaming variants: iter_contains, iter_find, iter_clean, iter_analyze
streamed = list(f.iter_clean(texts, chunk_size=1_000))
Use analyze / analyze_many when both a flag and cleaned text are needed; they avoid scanning each input twice. Custom mask callbacks work only with serial cleaning. Explicit worker counts are capped at 256, and applications with their own thread pools should set a smaller value to avoid oversubscription.
More information
- Documentation
- API reference
- Configuration guide — when to enable each option and performance tradeoffs
- How Profanex works
- Accuracy methodology and results
- Benchmark methodology and results
- Competitive benchmarks
- Limitations and threat model
- Fixture schema
- Lexicon provenance — upstream attribution, modifications, and data licensing
License
The Profanex software is MIT licensed. The packaged banned lexicon is a modified CC BY 4.0 dataset; see lexicon provenance.
Metadata
Release files for profanex 1.0.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 | Provenance | |
|---|---|---|---|---|
| profanex-1.0.0.tar.gz | 172.3 kB | Without provenance | Details |
Built distributions (wheels)
Total release size: 7.5 MB
Release files / profanex-1.0.0.tar.gz
| Download URL | profanex-1.0.0.tar.gz |
|---|---|
| Size | 172.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a303803ba9a72172494a4b7ac66183ba45357b2f65dce3bc2efb97155b0a2901
|
|
BLAKE2b-256 checksum How to use checksums |
294e7e4ef3f0e5966a97c03c6701397fd4db0416f3a9b79ed997eb28f4e8ba6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-win_amd64.whl
| Download URL | profanex-1.0.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 512.4 kB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8d4a07b7812a1534961260199c183361942164846f4356928368740e2ed7dd4a
|
|
BLAKE2b-256 checksum How to use checksums |
874b1565c6a066bcd716108abb59d8440607ea2f01581666eb3d0acacdf03bdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-win32.whl
| Download URL | profanex-1.0.0-cp311-abi3-win32.whl |
|---|---|
| Size | 449.3 kB |
| Tags | CPython 3.11 Windows x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
577115c6a468f0242f53f19db26f8689734f27ef109e93a070c8707a62ddce1a
|
|
BLAKE2b-256 checksum How to use checksums |
9a71184166102548695a9e4e3542a4d633892bfce904fcb7b235995eeee4ff7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_31_riscv64.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_31_riscv64.whl |
|---|---|
| Size | 593.7 kB |
| Tags | CPython 3.11 Linux glibc 2.31+ RISC-V 64 abi3 |
|
SHA-256 checksum How to use checksums |
ec62c26165712ee4ad6759861d45a5bda08e0f4eb33c98532fe49ed9b4094522
|
|
BLAKE2b-256 checksum How to use checksums |
9e12253ed4500fc4ee5110296854b877ca41b07352df433c03c3ca00ea63244e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 652.9 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
1d59b7122f898ec184ff52489aae6f1277d7382de558ae2c30b760f0f6538e8c
|
|
BLAKE2b-256 checksum How to use checksums |
c1fb9bf110f44062698b60c0184a9553bcca64b8220859a40c7c4113298b1644
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl |
|---|---|
| Size | 751.6 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ IBM System/390x abi3 |
|
SHA-256 checksum How to use checksums |
afe70fb63c9ef5b61df699ab5b32258da2159f8daafcfb634bd0017238d9ee64
|
|
BLAKE2b-256 checksum How to use checksums |
a0344b9b146385f53ddc7cfcdbeec716910c7ad8ee22b5c608e453260ac99bcb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl |
|---|---|
| Size | 655.9 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ PowerPC 64-le abi3 |
|
SHA-256 checksum How to use checksums |
af82c2e989d1e6b7ad466ffe03b82d8b953a37df4297030c7bd161b5f4cf0949
|
|
BLAKE2b-256 checksum How to use checksums |
3743b3e208897ae4e9f4bbf6ab6789a9247f7975c893654e90b842d0f3613bcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl |
|---|---|
| Size | 648.1 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ PowerPC 64-be abi3 |
|
SHA-256 checksum How to use checksums |
e98302bec2ea0a58e888e1037ad5ce770ece7e2c3a2133e01100ae0667ba7af3
|
|
BLAKE2b-256 checksum How to use checksums |
fd221dd3e5df0b8e5ec717d869a581aa3e5304f9be49a65f5e5ae0ce5a92cc02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_i686.manylinux2014_i686.whl |
|---|---|
| Size | 631.2 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
440810bee6494e763c28184c192e1c1caca156386c10b3d8f74038635071d6d6
|
|
BLAKE2b-256 checksum How to use checksums |
2c3991d0aca80c10b7b53522ef7ef469f7467f8260412bb1ede32ac85df1f883
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl |
|---|---|
| Size | 612.1 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ ARMv7l abi3 |
|
SHA-256 checksum How to use checksums |
300b62fc8487f58c41410b279bbecc2d9f6b6c738cfe53b6ad2d81aef7e47ebe
|
|
BLAKE2b-256 checksum How to use checksums |
a00552cc5c72cb0500a90a99d9b5d42c81afb1779b4607c49fe675ba899d1e65
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | profanex-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 606.9 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d67616e37dbffafb9d680eff4a185ac6c9847abd3347fcfabb84e583b99da750
|
|
BLAKE2b-256 checksum How to use checksums |
b540209e35d8e5b1ba171c5f199df9bafa11668e02309384c9a00be6c37026f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | profanex-1.0.0-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 565.8 kB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8dc4959cad7faf05f0c646d3e2ad11e469830c9e50b49904300481438d16d468
|
|
BLAKE2b-256 checksum How to use checksums |
69bdd0a85885683ff4d9b4aabb516c3ba5a56030def328f930a766aeba18fedf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / profanex-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl
| Download URL | profanex-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 615.8 kB |
| Tags | CPython 3.11 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
75c059152d815d7acff75bc967b2fd2639c5f5d6bc2cad3a7033ca4885d93dc4
|
|
BLAKE2b-256 checksum How to use checksums |
7f33db23a1c41394eeb10d505d7cb77f50c491944f7baf4c95087323ab6761a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for profanex 1.0.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.