ComputerysProfanityFilter 1.1.0

dotnet add package ComputerysProfanityFilter --version 1.1.0
                    
NuGet\Install-Package ComputerysProfanityFilter -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ComputerysProfanityFilter" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ComputerysProfanityFilter" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ComputerysProfanityFilter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ComputerysProfanityFilter --version 1.1.0
                    
#r "nuget: ComputerysProfanityFilter, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ComputerysProfanityFilter@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ComputerysProfanityFilter&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ComputerysProfanityFilter&version=1.1.0
                    
Install as a Cake Tool

ComputerysProfanityFilter

A .NET Standard 2.1 (C# version 9 for unity) profanity filter that censors known terms while recognizing common obfuscations such as character substitutions, punctuation, inserted whitespace, repeated letters, and leetspeak. The default term list is reasonable and covers swears, hate speech, and self-harm.

This library is currently used in STRAFTAT (as of the 1.4.9 update) to filter text chat, player names, lobby names, etc, albeit with a slightly cut down word list (swears removed).

Installation

NuGet

Install the package with the .NET CLI:

dotnet add package ComputerysProfanityFilter

Or add ComputerysProfanityFilter through the NuGet package manager in your IDE.

Unity Package Manager

In Unity, open Window > Package Manager, select +, then choose Add package from git URL..., then enter:

https://github.com/C0mputery/ComputerysProfanityFilter.git?path=/ComputerysProfanityFilter#upm-1.1.0

The #upm-1.1.0 suffix pins the package to version 1.1.0; change it to a newer upm-x.y.z tag to update. The UPM package requires Unity 2021.3 or newer.

Basic usage

Create one ProfanityList and reuse it when filtering messages. After construction, the instance can be used concurrently from multiple threads. Censor returns the original string unchanged when it finds no match.

using ComputerysProfanityFilter;

ProfanityList profanityFilter = new ProfanityList();
string censored = profanityFilter.Censor("Please don't be an a$$hole.");
// censored: "Please don't be an #######."

Use the optional second argument to choose the replacement character:

string censored = profanityFilter.Censor("Please don't be an a$$hole.", '*');
// censored: "Please don't be an *******."

Matching flexable, case-insensitive, it'll normalizes many substitutions (1337 speak, common enlgish rules), ignores selected punctuation within words, and collapses consecutive repeated letters. Entire matches, including their intervening punctuation, are replaced with the censor character.

Matching flexable, case-insensitive, it'll normalizes many substitutions (1337 speak, common enlgish rules). Punctuation and whitespace may be inserted within terms without preventing a match. Consecutive repeated letters are collapsed, so variants such as foooool can match fool. Matchs are as terms rather than arbitrary substrings, avoiding the Scunthorpe problem, cunt does not match inside Scunthorpe. Recognized punctuation can also act as a boundary between terms. Entire matches, including intervening whitespace and punctuation, are replaced with the censor character.

Detecting profanity

Use HasProfanity when you only need a yes/no result:

bool containsProfanity = filter.HasProfanity("That is a$$hole behavior.");

Use DetectAllProfanities when you need the locations and configured terms that matched:

var matches = filter.DetectAllProfanities("Sh!t happens.");

ProfanityMatch match = matches[0];
// match.Start: 0
// match.End: 4 (exclusive)
// match.Term: "shit"

Start is the zero-based inclusive index in the original input. End is the zero-based exclusive index. A match's Term is the configured term, even when the input uses an expanded or obfuscated form. Matches are returned in source order. Allow terms are excluded from all three operations.

Custom term list

Pass your own terms and normalization rules to the constructor. By default, supplied terms are expanded into several common English forms, so use base terms where appropriate. Set expandTermForms: false to match only the supplied forms after normalization.

using System.Collections.Generic;
using ComputerysProfanityFilter;

ProfanityList filter = new ProfanityList(
    terms: new[] { "spoiler", "example phrase" },
    allowTerms: new[] { "allowed word" },
    expandTermForms: false,
    expectedCharacters: DefaultProfanityList.ExpectedCharacters,
    joinerCharacters: DefaultProfanityList.JoinerCharacters,
    boundaryCharacters: new[] { '.', '-', '_' },
    characterMap: new Dictionary<char, string> { ['4'] = "a", ['@'] = "a" },
    sequenceMap: new Dictionary<string, string>()
);

string censored = filter.Censor("S-p-o-i-l-e-r ahead");
// censored: "############# ahead"

Default configuration

DefaultProfanityList exposes the built-in settings as read-only collections for reuse in custom filters: Terms, AlwaysCensorTerms, AllowTerms, ExpectedCharacters, JoinerCharacters, BoundaryCharacters, CharacterMap, and SequenceMap. Allow terms are compared to the original matched text using lowercase-invariant normalization only.

Allocation behavior

Censor is zero allocate on the heap when no term matches, it'll return the same string instance that was passed in. Only when a match is found will it rent a buffer from ArrayPool<char>.Shared and returns a string that is the same length as the input. The rented buffers can be reused across calls after the pool is warm, although rent may allocate when the pool has no suitable buffer available (and there are some other caveats with ArrayPool, but) Under typical use conditions, it will only allocate a string of the same size input.

Comparisons

Feature ComputerysProfanityFilter Profanity.Detector 0.1.8 BogaNet.BadWordFilter DotnetBadWordDetector Censored mk.profanity
Distribution NuGet + UPM (see above) NuGet NuGet NuGet NuGet NuGet
Last updated Aug 21, 2026 Jun 20, 2024 Feb 11, 2025 Jun 4, 2025 Jun 14, 2022 Jul 2, 2024
Matching approach Deterministic normalized term matching Dictionary/regex scanning + Scunthorpe heuristic Regex corpus + optional normalization; optional simple matching ML.NET binary classifiers Escaped wildcard patterns compiled to regex Tokenized exact list + optional Levenshtein
Case-insensitive matching ◐ It's ML
Word-boundary ◐ It's ML
Leetspeak normalization ◐ It's ML
Inserted punctuation handling
Inserted spaces handling ◐ It's ML
Repeated-letter handling ◐ It's ML
Multi-word phrase support
Match positions
Custom list
Allow list
Configurable censor character
Arbitrary custom-language terms/rules ✗ It's ML
Concurrency/thread safety ✓ Explicitly documented Mutable, not documented Mutable, not documented ✗ Uses PredictionEngine Mutable, not documented Mutable, not documented
External dependencies None None BogaNet.* infrastructure packages Microsoft.ML 1.7.0 None None
Trimming/AOT compatibility
Bundled profanity data ✓ 145 terms (2,573 with variations) ✓ 1,617 terms, the list is weird, read it, very much quantity over quality) ✓ ~4,600 entries (claims 5,000+ regexes) ✓ 4 ML Models ✓ 2,915 words
Bundled languages English English 25 4 0 English
Fuzzy matching ◐ It's ML
Confidence
Mutable
Patterns ✓ Regex ✓ Wildcards
URL/email moderation
Other symbol/content filters
Async rule loading
Target framework .NET Standard 2.1 and .NET 10 .NET Standard 2.0 .NET 8 .NET 8 .NET Standard 1.0 .NET Standard 2.1
License Apache-2.0 MIT MIT Apache-2.0 MIT MIT

Benchmarks

BenchmarkDotNet 0.15.8 results with .NET 10.0.10 on an AMD Ryzen 7 5800X (Windows 11). The suite compares this library with Profanity.Detector 0.1.8, BogaNet.BadWordFilter, DotnetBadWordDetector, Censored, and mk.profanity, using equivalent vocabularies where possible. Inputs are exactly 100, 1,000, 10,000, or 100,000 characters, made by repeating a fixed 10-message chat corpus containing ordinary, profane, and obfuscated text.

Benchmark run date: August 21, 2026.

Censoring

Results are grouped by vocabulary so each comparison uses the same term list. Times are mean time per Censor operation; allocation is managed allocation per operation.

Expanded default vocabulary (2,573 terms)
Mean Time 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter 2.468 us 29.422 us 302.077 us 2.981 ms
Profanity.Detector 109.157 us 1.165 ms 113.736 ms 1.943 s
BogaNet.BadWordFilter 151.999 us 1.464 ms 14.817 ms 166.816 ms
DotnetBadWordDetector 12.619 us 118.059 us 1.175 ms 12.425 ms
Censored 8.154 ms 8.146 ms 9.929 ms 25.445 ms
mk.profanity 51.646 us 391.885 us 3.838 ms 39.767 ms
Managed Allocation 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter - 2 KB 20 KB 195 KB
Profanity.Detector 8 KB 268 KB 68.00 MB 2.40 GB
BogaNet.BadWordFilter 520 B 29 KB 2.04 MB 205.42 MB
DotnetBadWordDetector 3 KB 24 KB 222 KB 2.15 MB
Censored 14.09 MB 14.17 MB 14.29 MB 15.52 MB
mk.profanity 4 KB 19 KB 151 KB 1.42 MB
Profanity.Detector raw vocabulary (1,617 terms)
Mean time 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter 2.903 us 33.929 us 336.551 us 3.429 ms
Profanity.Detector 72.138 us 751.393 us 73.684 ms 1.379 s
BogaNet.BadWordFilter 1.188 ms 9.846 ms 99.245 ms 1.041 s
DotnetBadWordDetector 13.296 us 117.788 us 1.173 ms 12.609 ms
Censored 2.872 ms 3.163 ms 4.114 ms 12.828 ms
mk.profanity 41.420 us 340.211 us 3.452 ms 34.629 ms
Managed Allocation 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter - 2 KB 20 KB 195 KB
Profanity.Detector 5 KB 290 KB 49.33 MB 2.11 GB
BogaNet.BadWordFilter 520 B 49 KB 2.98 MB 294.18 MB
DotnetBadWordDetector 3 KB 24 KB 222 KB 2.15 MB
Censored 5.65 MB 5.70 MB 5.92 MB 8.13 MB
mk.profanity 4 KB 20 KB 152 KB 1.42 MB
CPU-stress input

This benchmark uses a repeated аss… input. CPU-stress numbers re-run August 21, 2026.

Mean Time 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter 6.768 us 73.650 us 761.768 us 7.955 ms
Managed Allocation 100 chars 1,000 chars 10,000 chars 100,000 chars
ComputerysProfanityFilter 224 B 2 KB 20 KB 195 KB

Construction

Construction measurements create one filter instance. This system doesn't have free construction, so be a little bit wary of that. Make sure that you cache your instance after it's created.

Engine and vocabulary Mean Allocated
ComputerysProfanityFilter / expanded default (2,573 terms) 4.616 ms 5.39 MB
Profanity.Detector / same expanded vocabulary (2,573 terms) 5.490 us 32.98 KB
ComputerysProfanityFilter / Profanity.Detector raw vocabulary (1,617 terms) 1.364 ms 2.90 MB
Profanity.Detector / raw default vocabulary (1,617 terms) 4.399 us 25.58 KB
BogaNet.BadWordFilter / English sources 2.225 ms 1.64 MB
DotnetBadWordDetector / default model 29.899 ms 2.91 MB
Censored / equivalent expanded vocabulary 770.0 ns 20.18 KB
mk.profanity / equivalent expanded vocabulary 761.4 ns 20.30 KB

License

Copyright 2026 Christopher Rohland. This project is licensed under the Apache License 2.0. See the LICENSE file for the full license text.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 40 8/21/2026
1.0.0 48 8/20/2026