---
title: "How Matching Works"
description: "Learn the boundaries, normalization, ordering, and offsets behind detection."
---

> Documentation Index
> Fetch the complete documentation index at: https://profanity-kit.up2dul.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How Matching Works

Detection is whole-word matching. A configured `ass` matches in `ass!`, but not
inside `classic` or `assessment`:

```ts
detector.check("classic assessment"); // false
detector.check("ass!"); // true
```

Letters, combining marks, and numbers belong to a word. Punctuation,
whitespace, apostrophes, hyphens, and underscores are boundaries. Input and
dictionary entries use NFC normalization followed by lowercase casing.

`findAll()` scans the complete input, returns matches in source order, and
keeps repeated occurrences. Match `start` and `end` are UTF-16 offsets into the
original string. `filter()` replaces only matched spans and preserves all other
text.

`check()` exits as soon as it finds a match; `isClean()` is its readable
inverse. Both are closure-backed and safe as callbacks:

```ts
comments.filter(detector.isClean);
```

## Scope

Profanity Kit is a profanity detection toolkit, not a complete content
moderation system. It intentionally does not provide phrase matching,
substring matching, aggressive leetspeak expansion, or contextual moderation.
Create a detector with the configuration you need and apply human and
product-specific moderation policy around its results.

A match is not proof that a statement is abusive: some words have ordinary
meanings in other contexts. The Indonesian built-in pack omits `anjing`, `babi`,
`wedus`, `sempak`, and `setan` for that reason, while retaining the
profanity-specific form `anjg`. Add context-dependent terms to your own
`blockList` when your application needs stricter detection.

Source: https://profanity-kit.up2dul.dev/core-concepts/matching/index.mdx
