> ## Documentation Index
> Fetch the complete documentation index at: https://assemblyai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Filter profanity

export const ModelBadges = ({models}) => {
  return <div className="flex flex-wrap gap-2 -mt-3 mb-3 not-prose">
      {models.map(model => <span key={model} className="inline-flex items-center rounded-full bg-green-500/15 px-2.5 py-0.5 text-xs font-mono text-green-700 dark:text-green-400 ring-1 ring-inset ring-green-500/30">
          {model}
        </span>)}
    </div>;
};

<ModelBadges models={["universal-3-5-pro", "universal-streaming-english", "universal-streaming-multilingual"]} />

Automatically filter profanity from streaming transcripts in real time.

## Overview

Streaming profanity filtering lets you automatically mask profane words in your streaming transcripts in real time. When enabled, the API replaces profane words with asterisks in both **partial** and **final** turns before sending them to the client.

The mask uses the first letter of the word followed by `n - 1` asterisks (for example, `shit` becomes `s***`). Apostrophes, capitalization, and surrounding punctuation are preserved (for example, `shit's` becomes `s***'s`).

Profanity filtering supports all streaming models: `universal-3-5-pro`, `universal-streaming-english`, and `universal-streaming-multilingual`. It also works alongside other features such as `format_turns` and PII redaction.

<Tip>
  **Pre-recorded profanity filtering**

  For profanity filtering on pre-recorded audio, see [Filter profanity from transcripts](/guardrails/filter-profanity-from-transcripts).
</Tip>

## Connection parameters

| Parameter               | Type    | Required | Default | Description                                                                                                                                                                                                                                                                      |
| ----------------------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `filter_profanity`      | boolean | No       | `false` | Enable real-time profanity filtering. When `true`, profane words in both partial and final turns are masked with asterisks (first letter preserved). The server accepts the truthy strings `true`, `1`, and `yes`. Invalid values cause the WebSocket to close with code `3006`. |
| `include_partial_turns` | boolean | No       | `true`  | When `false`, the API only sends final turns. Useful with `filter_profanity: true` if you display partials directly to end-users and want to avoid any unmasked profanity flashing during word completion.                                                                       |

## Quickstart

Set `filter_profanity` to `true` when you open the WebSocket.

<Tabs>
  <Tab language="python" title="Python" default>
    ```python theme={null}
    CONNECTION_PARAMS = {
        "sample_rate": 16000,
        "speech_model": "universal-3-5-pro",
        "filter_profanity": True,
    }
    ```
  </Tab>

  <Tab language="python-sdk" title="Python SDK">
    ```python theme={null}
    client.connect(
        StreamingParameters(
            sample_rate=16000,
            speech_model="universal-3-5-pro",
            filter_profanity=True,
        )
    )
    ```
  </Tab>

  <Tab language="javascript" title="Javascript">
    ```javascript theme={null}
    const CONNECTION_PARAMS = {
      sample_rate: 16000,
      speech_model: "universal-3-5-pro",
      filter_profanity: true,
    };
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    ```javascript theme={null}
    const transcriber = client.streaming.transcriber({
      sampleRate: 16_000,
      speechModel: "universal-3-5-pro",
      filterProfanity: true,
    });
    ```
  </Tab>
</Tabs>

<Tip>
  **Suppress unmasked partials with include\_partial\_turns=false**

  Profanity filtering applies to both partial and final turns, but during word-completion an unmasked partial can briefly appear before the model resolves the word and applies the mask. If your application surfaces partials directly to end-users (for example a live caption stream or voice-agent UI), set `include_partial_turns: false` on the connection to suppress all partial turns and only receive masked finals. The default is `true` (partials enabled), so this requires an explicit opt-out.
</Tip>

### Example output

With `filter_profanity=true`, a final turn might look like:

```plain theme={null}
s*** is what you say when you stub your toe.
```

The mask preserves word length, apostrophes, and surrounding punctuation, so a word like `shit's` is returned as `s***'s` and `motherfucker` becomes `m***********`.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Why are some profane words still appearing in the transcript?" theme="dark" iconColor="white">
    The streaming filter targets the same word list as pre-recorded profanity
    filtering and only masks words on that list. Some words you might consider
    profane, such as `crap` and `damn`, are intentionally not masked and pass
    through unchanged. If you need stricter filtering, apply your own
    post-processing on top of the masked transcript.
  </Accordion>

  <Accordion title="An unmasked profane word briefly appeared in a partial turn">
    Profanity masking applies during word classification, so an unmasked partial
    can briefly appear before the word is fully recognized and masked. If your
    UI surfaces partials directly to users, set `include_partial_turns: false`
    on the connection. Final turns are always masked.
  </Accordion>
</AccordionGroup>
