# fail2ban regex tester

> Free online fail2ban regex tester. Paste log lines, pick any built-in filter or write a failregex with <HOST>, and see matches, missed lines and IPs to ban.
>
> Source: https://fail2ban.dev/tools/regex-tester/ · Updated 2026-10-25 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

## How to use the regex tester


1. **Pick a filter** from the list (for example `sshd`, `nginx-http-auth` or `postfix`) — its failregex, ignoreregex and prefregex load exactly as fail2ban 1.1.1 compiles them — or choose *Custom regex…* and write your own.
2. **Paste log lines** from the service: `tail -n 200 /var/log/auth.log`, `journalctl -u ssh -n 200`, an nginx error log… *Load sample log lines* fills in real lines from fail2ban's own test suite.
3. **Read the result.** Each line shows ✓ when a failregex matched, the detected timestamp (underlined — fail2ban removes it before matching) and the captured host in orange. The table underneath counts failures per address and flags the ones that would reach `maxretry`.

When it works here, confirm on the server with [`fail2ban-regex`](/fail2ban-regex/) — the command at the bottom of the tool is ready to copy.

## How accurate is it?

The tester is a JavaScript port of the code fail2ban uses to decide whether a line is a failure: date detection with fail2ban's own date templates, `prefregex` and `<F-CONTENT>`, tag substitution for `<HOST>`, `<ADDR>`, `<IP4>`, `<IP6>`, `<DNS>`, `<SUBNET>`, `<F-ID>` and custom `<F-…>` groups, `ignoreregex`, and multi-line failure IDs (`<F-MLFID>`, `<F-NOFAIL>`). Built-in filters are translated from the regexes fail2ban itself compiles, including Python-only features such as conditional groups.

We check it against fail2ban's own results on every sample log line shipped in the fail2ban test suite: it agrees on **99.7% of 1,028 lines** (the few differences are rare multi-line SSH session cases). Two things still differ from a real server:

- **Python vs JavaScript regex.** Custom regexes are converted from Python syntax (`(?P<name>…)`, `(?P=name)`); conditional groups `(?(name)…)` only work in the built-in filters. Character classes like `\w` match only ASCII letters in the browser.
- **Time windows.** The tester counts every matched line, as if all of them fell inside `findtime`. fail2ban also ignores lines older than `findtime` and lines without a recognisable timestamp.

## failregex cheat sheet

| Tag | Matches | Use it for |
|---|---|---|
| `<HOST>` | IPv4, IPv6 or a hostname | the address to ban (most filters) |
| `<ADDR>` | IPv4 or IPv6 only | when the log never contains hostnames |
| `<IP4>` / `<IP6>` | one address family | special cases |
| `<SUBNET>` | an address with optional `/cidr` | logs that report networks |
| `<F-USER>…</F-USER>` | any text you wrap | capture the user name (shown in results and mails) |
| `<F-ID>…</F-ID>` | a failure ID that isn't an IP | ban by another identifier |
| `<F-CONTENT>…</F-CONTENT>` | the rest of the line | inside `prefregex` only |

A few rules that save hours:

- **Anchor with `^`.** fail2ban removes the timestamp first, so `^` means "right after the date" for most logs. `%(__prefix_line)s` in built-in filters also skips the syslog hostname and `daemon[pid]:` prefix.
- **Avoid greedy `.*` before `<HOST>`.** An attacker can put an IP into a user name field; `.*` lets the regex grab the wrong address. Match the fixed text right before the address instead.
- **One regex per line.** Multiple `failregex` lines are tried in order; the first one that matches wins.

More detail in [how to write a custom filter](/filters/custom/), or let the [filter generator](/tools/filter-generator/) write a first version from one log line.

## FAQ

### Is there an online fail2ban regex tester?

Yes — this page. It runs fail2ban's matching rules in your browser: choose a built-in filter or type a failregex with `<HOST>`, paste log lines, and it shows which lines match, the extracted IP and the timestamp fail2ban would use. Your logs never leave your computer.

### Why does my failregex not match?

The usual causes: the regex expects the timestamp (fail2ban strips it first), it lacks a `<HOST>` or `<F-ID>` group, it uses greedy `.*` that skips past the address, or the log line has a prefix such as `hostname sshd[123]:` the regex doesn't account for. Paste the line here and compare against the built-in filter for the same service.

### Can I test multiline regex here?

Yes. Built-in filters that use `maxlines` (and `<F-MLFID>` correlation such as `sshd`) are processed line by line with a buffer, as fail2ban does. For custom multi-line patterns, use `<SKIPLINES>` and test the final version with `fail2ban-regex`.
