# Report fail2ban bans to AbuseIPDB

> Report fail2ban bans to AbuseIPDB: API key setup, categories per jail, which jails to report, rate limits, keeping log lines private, plus blocklist.de and IPThreat.
>
> Source: https://fail2ban.dev/guides/abuseipdb/ · Updated 2026-10-25 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

To report bans to AbuseIPDB, put your API key in `/etc/fail2ban/action.d/abuseipdb.local` and add `%(action_abuseipdb)s[abuseipdb_category="18,22"]` as a second action line in the jail. fail2ban then calls AbuseIPDB's v2 report API with `curl` on every new ban, sending the IP, the categories and the matched log lines as the comment.

```ini
[Init]
abuseipdb_apikey = YOUR_API_KEY
```
[sshd]
enabled  = true
maxretry = 5
action   = %(action_)s
           %(action_abuseipdb)s[abuseipdb_category="18,22"]
```


1. **Create an AbuseIPDB account** and an API key (Account → API). The free plan allows 1,000 checks and reports per day combined.
2. **Store the key** in `/etc/fail2ban/action.d/abuseipdb.local` as shown above, and restrict it: `sudo chmod 600 /etc/fail2ban/action.d/abuseipdb.local`. Keeping the key out of `jail.local` means you can share your jail config without leaking it.
3. **Make sure `curl` is installed.** The action is a `curl -sSf` call to `https://api.abuseipdb.com/api/v2/report`.
4. **Add the action to the jails you want to report.** Keep `%(action_)s` as the first line. That's the actual firewall ban. Without it the jail would report but not block.
5. **Reload and check:** `sudo fail2ban-client -t && sudo fail2ban-client reload`, then `sudo fail2ban-client get sshd actions` should list both `nftables` (or your ban action) and `abuseipdb`.

Setting `action` in a jail replaces the default action list for that jail only ([jail options](/config/jail-options/)). The `action_abuseipdb` shortcut in `jail.conf` is just the action name, so you pass parameters to it in brackets. The action sets `norestored = 1`: bans that fail2ban restores from its database after a restart aren't reported a second time.

## Categories per jail

`abuseipdb_category` is required. AbuseIPDB rejects reports without a category. Use comma-separated IDs, from the list in [action.d/abuseipdb.conf](/actions/#action-abuseipdb):

| Jail | Suggested categories | IDs |
|---|---|---|
| `sshd` | Brute-Force + SSH | `18,22` |
| `postfix-sasl`, `dovecot` | Brute-Force | `18` |
| `nginx-http-auth`, `apache-auth`, WordPress/app logins | Brute-Force + Web App Attack | `18,21` |
| `nginx-botsearch`, `apache-noscript` | Web App Attack + Bad Web Bot | `21,19` |
| `postfix` (spam rejects) | Email Spam | `11` |
| `recidive` | Brute-Force (+ Port Scan if relevant) | `18` or `18,14` |

Other IDs from the list: 4 DDoS Attack, 9 Open Proxy, 10 Web Spam, 20 Exploited Host, 23 IoT Targeted. The full descriptions are on AbuseIPDB's categories page.

```ini
[postfix-sasl]
enabled = true
backend = systemd
action  = %(action_)s
          %(action_abuseipdb)s[abuseipdb_category="18"]

[recidive]
enabled = true
action  = %(action_)s
          %(action_abuseipdb)s[abuseipdb_category="18"]
```

A report says "this address attacked me". The action file itself (and the fail2ban developers) recommend reporting only when you're confident:

- **[recidive](/config/recidive/)**: the address was banned repeatedly. The best candidate.
- **Jails with a high `maxretry`**, well beyond a user mistyping a password.
- **Filters that humans rarely trigger**: SSH with password login disabled (any failure is a bot), bot-search filters, SASL failures on an MTA with few users.

If you just want to know about bans yourself, [email alerts](/config/email-alerts/) are the private alternative. Don't report from jails that regularly catch your own users, such as webmail or Nextcloud with a low `maxretry`. A false report against a customer's office IP or a mobile carrier's CGNAT address can get that address blocked elsewhere. And don't report addresses from a misconfigured reverse proxy: if every ban is your proxy's IP, fix that first.

## Rate limits

- **Daily quota:** the free plan allows 1,000 report and check requests per day. Paid plans allow more. A busy server with several reporting jails can hit 1,000. The API then answers HTTP 429 and `curl -f` exits non-zero, so `/var/log/fail2ban.log` shows a failed `abuseipdb` action. The firewall ban itself still works, because it's a separate action.
- **Same IP once per 15 minutes:** reporting an address again within 15 minutes is rejected with 429. It happens when two jails ban the same IP at once. It's harmless, but noisy in the log.

If you hit the daily limit regularly, report only from `recidive`.

## Privacy: what the report contains

The default action sends the matched log lines (`<matches>`, cut to 1,000 characters) as the report's comment, and AbuseIPDB shows comments publicly. Depending on the filter, those lines can contain:

- your server's **hostname** (syslog prefix) and **local IP** (`lip=` in Dovecot lines),
- **usernames** that were tried, which on a mail server are often your real users' addresses,
- request paths, query strings and user agents from web logs.

AbuseIPDB's documentation asks reporters to strip personal data. The simplest fix is to override the ban command with a fixed comment:

```ini
[Definition]
actionban = curl -sSf "https://api.abuseipdb.com/api/v2/report" -H "Accept: application/json" -H "Key: <abuseipdb_apikey>" --data-urlencode "comment=fail2ban: <failures> failed logins (jail <name>)" --data "ip=<ip>" --data "categories=<abuseipdb_category>"

[Init]
abuseipdb_apikey = YOUR_API_KEY
```

## Check that reports are sent

fail2ban only logs action output when something fails, so look in two places:

```bash
sudo grep -i abuseipdb /var/log/fail2ban.log

# your reports, in the AbuseIPDB dashboard (Account → Reports)
```

## blocklist.de

[blocklist.de](/actions/#action-blocklist_de) collects reports and forwards them to the abuse contacts of the attacking networks. Register a server there to get an API key, then:

```ini
[DEFAULT]
sender              = server-email-registered@example.com
blocklist_de_apikey = YOUR_BLOCKLIST_DE_KEY

[sshd]
enabled = true
action  = %(action_)s
          %(action_blocklist_de)s
```

## IPThreat

The `ipthreat` action reports to ipthreat.net. Request an API key with bulk-report permission, put it in `/etc/fail2ban/action.d/ipthreat.local` under `[Init]` as `ipthreat_apikey = ...`, and add `ipthreat[]` as an extra action line. The defaults report flag `8` (BruteForce) with the jail name as the system. Override them with `ipthreat[ipthreat_system="SSH", ipthreat_flags="8"]`. It sends only the IP, flags, system and the note "fail2ban", no log lines.

## FAQ

### How do I report fail2ban bans to AbuseIPDB?

Put `abuseipdb_apikey = YOUR_KEY` under `[Init]` in `/etc/fail2ban/action.d/abuseipdb.local`, then add `%(action_abuseipdb)s[abuseipdb_category="18,22"]` as a second line under `action = %(action_)s` in the jail. Reload fail2ban. Each new ban is reported with `curl` to AbuseIPDB's v2 API.

### Which AbuseIPDB categories should I use for SSH?

Use `18,22`: 18 is Brute-Force and 22 is SSH. AbuseIPDB recommends combining 22 with a more specific category. For web logins use `18,21` (Web App Attack), for mail authentication `18`, and for repeat offenders from recidive `18`.

### What is the AbuseIPDB rate limit for fail2ban?

The free plan allows 1,000 check and report requests per day, and the same IP can only be reported once every 15 minutes. Over the limit, the API returns HTTP 429 and fail2ban logs a failed action, but the firewall ban still works. Report from fewer jails, for example only recidive, if you hit it.

### Does the fail2ban abuseipdb action share my log lines?

Yes. By default it sends up to 1,000 characters of matched log lines as the public comment, which can include your hostname, local IP and tried usernames. Override `actionban` in `abuseipdb.local` with a fixed comment if you don't want to publish them.
