Regex Filter

Match message content against your own regular expressions. Use it when a literal word list isn't expressive enough — scam URL shapes, formatted account handles, obfuscation patterns.

Open AutoMod
Custom Regular Expressions

Regex Filter evaluates each message against an admin-supplied list of Python-flavoured regular expressions. It is the escape hatch for patterns that are too structured for a word list and too narrow for the shared link or invite filters.

What is this?

A rule that matches messages against your own regular expressions. Each pattern runs with a 50 ms timeout, so even badly-formed regex can't hang the bot. The first matching pattern in your list wins, and matching is case-insensitive by default.

Why you might want it

For when you already know what regex is and you want to use it here. Scam URL shapes, formatted account handles, leetspeak variants of slurs the word filter misses. If you don't write regex day to day, start with Word Filter or Link Filter instead. Every pattern you add should spend at least a week in Log Only mode before going Live.

Setup time: varies (per pattern)Difficulty: Advanced. Read carefully before changing.
How this rule works
Checks:The message's text content only.
Triggers when:Any pattern in patterns matches the message content (case-insensitive by default). Patterns are tried in order; the first match wins.
Ignores:Exempt roles, exempt channels, and allowlist words (Regex Filter is a content-match trigger, so allowlist entries short-circuit the rule if the message contains any of them).
Counts toward spam buffers:No — this trigger is per-message, not volumetric.

Why use this rule?

  • Catches scam payloads with a recognisable shape but an ever-changing word list — fake Nitro giveaways, Steam-trade bait, crypto-airdrop URLs.
  • Flags structured identifiers you don't want posted in chat — credit card number shapes, account handles, support ticket IDs leaked into public channels.
  • Lets you tighten Word Filter gaps with anchors, digit classes, or character-set alternations that a flat word list cannot express.
  • Gives power users a surgical tool when a preset package, Link Filter, or Invite Filter is either too broad or too narrow.

What it detects

Messages whose content matches any admin-supplied regular expression in trigger_config.patterns. Each pattern is run with Python regex-module semantics, defaults to case-insensitive, and is evaluated with a 50 ms per-pattern timeout. Evaluation stops at the first pattern that matches.

Example Match
S
scammer_99Today at 03:11
claim your free nitro here: https://bit.ly/xyz
AutoMod: matched — pattern \b(?:free|cheap)\s+(?:nitro|discord gift)\b. Action: delete + warn.

What it does NOT detect

  • Text inside embeds, attachment filenames, sticker names, or reactions — only the raw message content is scanned.
  • Unicode-normalised variants unless your pattern explicitly covers them. Stylised fonts like ⓕⓡⓔⓔ ⓝⓘⓣⓡⓞ bypass a plain \bfree\b pattern.
  • Patterns longer than 200 characters — oversized patterns are rejected before matching and logged at WARNING level.

Configuration

FieldTypeDefaultWhat it means
patternslist of strings[]Python-flavoured regular expressions. Each is tried in order until one matches. Remember to double-escape backslashes when editing raw JSON (\\b in JSON is \b at runtime).
ℹ️
Note
The rule-level case_sensitive toggle is honoured. When off (the default) Arkanis sets the IGNORECASE flag automatically; when on, the pattern is matched verbatim. The rule-level word_boundary toggle does not apply — write your own \b anchors inside the pattern.

Recommended starter settings

Two narrow, high-signal patterns to start with. Both are anchored, both use word boundaries, and both target a shape that appears almost exclusively in scams.

{
  "patterns": [
    "\\b(?:free|cheap)\\s+(?:nitro|discord gift)\\b",
    "https?://(?:bit\\.ly|tinyurl\\.com|t\\.co)/\\S+"
  ]
}

Run with Mode: Log Only for at least a week. Every regex you write should spend time in Log Only so you can count false positives before any enforcement action touches a real member.

Common false positives

  • Unescaped metacharacters. Admins new to regex paste a.b.c thinking it matches a literal string, but . matches any character — axbyc, a1b2c, and so on all match. Escape every literal dot, ?, (, and ).
  • Case-insensitive surprise. A pattern like [A-Z]{5,} intended to match shouty all-caps still matches lowercase text because IGNORECASE is on by default. Turn on the rule's case_sensitive toggle if you want the pattern matched verbatim.
  • Over-broad alternations. (free|gift|give) without word boundaries fires on words like freedom, gifting, giveaway. Always anchor with \b.
  • Overlap with legitimate link discussion — a URL-shape pattern will catch developers pasting shortener URLs into a dev channel. Combine with exempt channels for your staff areas.

How to test this rule safely

1

Set the rule to Log Only

Log Only records matches without taking any action. Every regex change deserves a pass in Log Only before going Live.

2

Start with one well-anchored test pattern

Add a single, obviously-safe pattern like ^TEST_AUTOMOD_REGEX_\d+$ to patterns. Anchored patterns are easy to reason about and impossible to misfire on real content.

3

Post a matching test message

In a private channel, post TEST_AUTOMOD_REGEX_42. Check the Event Log dashboard — the entry should show matched_pattern equal to your exact regex string (not the matched text).

4

Confirm allowlist and exempt roles work

Add a fragment of your test message to allowlist_words and post again — no Event Log entry. Remove it, add one of your roles to Exempt Roles, post as that role — no Event Log entry.

5

Swap in your real patterns and tune

Replace the test pattern with your production list. Leave the rule in Log Only for a week, review the Event Log, and tighten any pattern that shows false positives.

6

Flip to Live

Once the match rate looks clean, switch the rule from Log Only to Live.

Known current behavior

  • Current behavior: every pattern runs with a hard 50 ms timeout. Arkanis uses the third-party regex library as a hard import, which supports per-call timeouts. A pattern that would take longer than 50 ms to evaluate on the current message is interrupted, the exception is caught, and evaluation continues with the next pattern. This makes classic ReDoS shapes like (a+)+$ safe to save — they will simply never match in practice.
  • Current behavior: patterns longer than 200 characters are rejected outright. Before a pattern is compiled, its length is checked against MAX_REGEX_LENGTH (200). Oversized patterns are skipped and logged at WARNING with the guild and rule context. Production moderation regexes fit comfortably under this cap; anything longer is almost always a mistake or an attack.
  • Current behavior: patterns are tried sequentially and the first match wins. Ordering matters if you care about which pattern is reported in the Event Log. Put the most specific, highest-signal patterns first.
  • Current behavior: matched_pattern is the pattern string, not the matched text. Dashboards and the Event Log will show the raw regex (for example \b(?:free|cheap)\s+nitro\b) rather than the snippet that tripped it. Name patterns clearly if you want recognisable rows in the log.
  • Current behavior: the rule-level case_sensitive toggle is honoured. Default is off: IGNORECASE is applied automatically. Turn it on when you need a pattern like [A-Z]{5,} to actually mean uppercase.
  • Current behavior: patterns are not validated at rule-creation time. An invalid regex (for example an unmatched [) is saved to the rule and only logged when a message arrives and the compile fails. Admins get no upfront feedback; watch the Event Log after saving any non-trivial pattern.
  • Current behavior: invalid patterns do not crash the rule. Any exception raised by the matcher — compile errors, timeouts, unexpected Unicode failures — is caught, logged at WARNING, and the evaluator moves on to the next pattern. One bad pattern will not disable the other entries in the list.
  • Current behavior: allowlist words apply before patterns run. If any allowlist entry appears anywhere in the message (substring-matched, lowercase), the rule is skipped entirely. Keep allowlist entries specific — a short fragment like nitro would accidentally neutralise every pattern above.

Action reference

Regex Filter pairs with any of the five AutoMod actions. Unlike Word Filter, the message is not force-deleted ahead of the action — deletion is controlled by action_config.delete_message (default true) or by choosing the delete action directly. Most scam-pattern rules run as delete plus a short mute.

💡
Tip
See: AutoMod Actions → for the canonical reference on what delete, warn, mute, strike, and ban actually do, plus every action_config field and required Discord permission.