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.