AbuseIPDB APIv2 documentation

The AbuseIPDB API allows you to utilize our database programmatically. This is most commonly done through Fail2Ban, which comes prepackaged with an AbuseIPDB configuration. Grab a new API key at from account dashboard.

Configuring AbuseIPDB with Fail2Ban

Follow our APIv1 tutorial. APIv2 works the same way except for slight alterations to the cURL request. In APIv2, actionban command in Fail2Ban’s abuseipdb.conf will looks like:

actionban = curl --fail 'https://api.abuseipdb.com/api/v2/report' \
    -H 'Accept: application/json' \
    -H 'Key: <abuseipdb_apikey>' \
    --data-urlencode 'comment=<matches>' \
    --data-urlencode 'ip=<ip>' \
    --data 'categories=<abuseipdb_category>'
  • The category parameter has been renamed to categories.
  • Your API key can still be passed in the query as key, but it is recommended to use the HTTP header.
  • The IP value should be url encoded because IPv6 addresses have colons.
  • Request JSON with “Accept: application/json”

That’s it! You’ve migrated.

check Endpoint

The check endpoint accepts a single IP address (v4 or v6). Optionally you may set the days parameter to only return reports within the last x amount of days.

curl -G https://api.abuseipdb.com/api/v2/check \
  --data-urlencode "ipAddress=127.0.0.1" \
  -d maxAgeInDays=90 \
  -d verbose \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json"

This will yield the following JSON response:

{
  "data": {
    "ipAddress": "127.0.0.1",
    "isPublic": false,
    "ipVersion": 4,
    "isWhitelisted": false,
    "abuseConfidenceScore": 0,
    "countryCode": "US",
    "totalReports": 1039,
    "countryName": "United States",
    "reports": [
      {
        "reportedAt": "2018-02-26 14:38:58",
        "comment": "Edward Hyde has done it again!",
        "categories": [
          18,
          22
        ],
        "reporterId": 1,
        "reporterCountryCode": "US",
        "reporterCountryName": "United States"
      }
    ]
  }
}

The desired data is stored in the data property. Here you can inspect details regarding the IP address queried, such as version and country of origin. And of course there is the valuable abusive reports. In this case “abuseConfidenceScore” is 0 because 127.0.0.1 is a loopback address, and therefore cannot be an abusive IP address (unless you have a split personality).

The “isWhitelisted” property reflects whether the IP is spotted in any of our whitelists. Our whitelists give the benefit of the doubt to many IPs, so it generally should not be used as a basis for action. The “abuseConfidenceScore” is a better basis for action, because it is nonbinary and allows for nuance.

The maxAgeInDays parameter determines how far back in time we go to fetch reports. In this example, we ask for reports no older than 90 days. The default is 30.

Reports are included in this response because the verbose flag was added. Omitting the verbose flag will exclude reports and the country name field. If you want to keep your response payloads light, this is highly recommended.

The IP address should be url-encoded, because IPv6 addresses use colons, which are reserved characters in HTTP requests.

Note: the following fields are not always included in the response: isWhitelisted, abuseConfidenceScore, totalReports.

Parameters:

field required default min max
ipAddress yes      
maxAgeInDays no 30 1 365
verbose no      

blacklist Endpoint

The blacklist is the culmination of all of the valiant reporting by AbuseIPDB users. It’s a list of the most reported IP addresses. Fetch it with:

curl -G https://api.abuseipdb.com/api/v2/blacklist \
  -d countMinimum=15 \
  -d maxAgeInDays=60 \
  -d confidenceMinimum=90 \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json"

And the JSON response:

{
  "data": [
    {
      "ipAddress": "5.188.10.179",
      "totalReports": 560,
      "abuseConfidenceScore": 100
    },
    {
      "ipAddress": "185.222.209.14",
      "totalReports": 529,
      "abuseConfidenceScore": 100
    },
    {
      "ipAddress": "191.96.249.183",
      "totalReports": 325,
      "abuseConfidenceScore": 100
    }
  ]
}

The body is an array where each element contains the IP address, the total number of reports, and our confidence of abuse score. We recommend you filter by abuseConfidenceScore, which is our calculated evaluation on how abusive the IP is based on the users that reported it (more). However, you can also filter by raw report count, which effectively gives every distinct reporter an equal weight. The maxAgeInDays parameter determines how far back in time we go to fetch reports counted for the countMinimum parameter. In this example, we ask for reports no older than 60 days. The default is 30. In the meta block we include generatedAt property that lets you check for the freshness of the list, if you’d like.

If you prefer a simple newline-separated plaintext response. Set the plaintext flag via a GET flag or the Accept header:

curl -G https://api.abuseipdb.com/api/v2/blacklist \
  -d countMinimum=15 \
  -d maxAgeInDays=60 \
  -d confidenceMinimum=90 \
  -d plaintext \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json"

or

curl -G https://api.abuseipdb.com/api/v2/blacklist \
  -d countMinimum=15 \
  -d maxAgeInDays=60 \
  -d confidenceMinimum=90 \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: text/plain"

To receive:

5.188.10.179
185.222.209.14
95.70.0.46
191.96.249.183
115.238.245.8
122.226.181.164
122.226.181.167

No report count or confidence score is included, but the list will meet your parameters. This format is very useful for UNIX scripting. The freshness timestamp can be found in the HTTP header as X-Generated-At.

Subscribers may set the self flag, which configures the blacklist generator to only consider reports from their own account.

⚠️ If you plan into import these IPs into iptables, it is critical that the list is either continually updated or, if it cannot be updated, cleared from iptables. Report value decay over time, cycling out IPs that stop abusing. AbuseIPDB is not responsible for dropped connections from legitimate sources.

Parameters:

field required default min max subscriber feature
maxAgeInDays no 30 1 365 yes
countMinimum no 10 10 1000 yes
confidenceMinimum no 100 25 100 yes
limit no 10,000 1   restricted, see below
plaintext         no
self         yes

Blacklist Caching

By default, the blacklist with default parameters is cached for one day. Results for premium subscribers are cached for one hour.

Blacklist IP Truncation

To conserve bandwidth, the number of IP addresses included in the list is capped to 10,000. Premium subscribers can overcome this limit. All users can set it between 1 and 10,000.

report Endpoint

Reporting IP addresses is the core feature of AbuseIPDB. When you report what you observe, everyone benefits, including yourself. To report an IP address, send a POST request. At least one category is required, but you may add additional categories using commas to separate the integer IDs. Related details can be included in the comment field.

⚠️ STRIP ANY PERSONALLY IDENTIFIABLE INFORMATION (PPI); WE ARE NOT RESPONSIBLE FOR PPI YOU REVEAL.

curl https://api.abuseipdb.com/api/v2/report \
  --data-urlencode "ip=127.0.0.1" \
  -d categories=18,22 \
  --data-urlencode "comment=SSH login attempts with user root." \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json"

Response:

{
  "data": {
    "ipAddress": "127.0.0.1",
    "abuseConfidenceScore": 52
  }
}

In the body, we get the updated abuseConfidenceScore.

Parameters:

field default restrictions description
ip required   A valid IPv4 or IPv6 address.
categories required A valid category id value. Comma separated values; Reference
comment   Max characters (bytes): 1024 Related information (server logs, timestamps, etc.)

Test IP Addresses

Reporting 127.0.0.2 will simulate a short term rate limit. This is useful for application testing.

{
  "errors": [
    {
      "detail": "You can only report the same IP address (`127.0.0.2`) once in 15 minutes.",
      "status": 429,
      "source": {
        "parameter": "ip"
      }
    }
  ]
}

check-block Endpoint

Not satisfied with checking a single IP address? Check an entire subnet! Use cases for this are slim, but it’s great for research or high-level analysis.

Please do not use this endpoint as a blacklist, as subnet checks are intensive. Casting a wide net (e.g. /16) or searching far back in time (e.g. maxAgeInDays=365) will likely cause a server timeout, and you will receive a 500 Internal Server Error response.

curl -G https://api.abuseipdb.com/api/v2/check \
  --data-urlencode "network=127.0.0.1/24" \
  -d maxAgeInDays=90 \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json"

Sample response:

{
  "data": {
    "networkAddress": "127.0.0.0",
    "netmask": "255.255.255.224",
    "minAddress": "127.0.0.1",
    "maxAddress": "127.0.0.30",
    "numPossibleHosts": 30,
    "addressSpaceDesc": "Loopback",
    "reportedAddress": [
      {
        "ipAddress": "127.0.0.1",
        "numReports": 214,
        "mostRecentReport": "2018-03-10T19:00:58+00:00",
        "abuseConfidenceScore": 0,
        "countryCode": null
      },
      {
        "ipAddress": "127.0.0.2",
        "numReports": 3,
        "mostRecentReport": "2018-03-10T19:06:04+00:00",
        "abuseConfidenceScore": 0,
        "countryCode": null
      },
      {
        "ipAddress": "127.0.0.3",
        "numReports": 1,
        "mostRecentReport": "2018-03-10T19:09:31+00:00",
        "abuseConfidenceScore": 0,
        "countryCode": null
      },
      {
        "ipAddress": "127.0.0.4",
        "numReports": 1,
        "mostRecentReport": "2018-02-15T18:58:38+00:00",
        "abuseConfidenceScore": 0,
        "countryCode": null
      },
      {
        "ipAddress": "127.0.0.5",
        "numReports": 2,
        "mostRecentReport": "2018-03-10T19:41:08+00:00",
        "abuseConfidenceScore": 0,
        "countryCode": null
      }
    ]
  }
}

Parameters:

field required default min max
network yes      
maxAgeInDays no 30 1 365

bulk-report Endpoint

If reporting IP addresses one by one may not seem efficient to you, we offer an endpoint that allows a CSV file of IPs to be reported in one shot. Such a list can be extracted from your secure log file or similar. See the bulk report form for a guide.

curl https://api.abuseipdb.com/api/v2/bulk-report \
  -F csv=@report.csv \
  -H "Key: $YOUR_API_KEY" \
  -H "Accept: application/json" \
  > output.json

The response will inform you how many IPs were successfully reported, and which ones were rejected and why:

{
  "data": {
    "savedReports": 60,
    "invalidReports": [
      {
        "error": "Duplicate IP",
        "input": "41.188.138.68",
        "rowNumber": 5
      },
      {
        "error": "Invalid IP",
        "input": "127.0.foo.bar",
        "rowNumber": 6
      },
      {
        "error": "Invalid Category",
        "input": "189.87.146.50",
        "rowNumber": 8
      }
    ]
  }
}

API Daily Rate Limits

The API rate limits are currently as follows:

  Standard Webmaster Supporter Basic Subscription Premium Subscription
check 1,000 3,000 5,000 10,000 50,000
blacklist 5 10 20 100 500
report 1,000 1,000 1,000 10,000 50,000
check-block 100 1,000 2,000 10,000 50,000
bulk-report 5 10 20 100 500

Upon reaching your daily limit, you will receive a HTTP 429 Too Many Requests status. With the request header “Accept: application/json”, you will receive the following body:

{
  "errors": [
    {
      "detail": "Authentication failed. You are either missing your API key or it is incorrect. Note: The APIv2 key differs from the APIv1 key.",
      "status": 401
    }
  ]
}

Otherwise, by default, you get an entire HTML page, which is why you should set “Accept: application/json” when working with the API programmatically.

Error Handling

HTTP status codes are the most reliable method of determining the status of the API response. After all, that is the sole purpose of the codes. When we encounter at least one application error, a JSON response with a collection of errors is returned. The structure conforms to the JSON API spec:

{
  "errors": [
    {
      "detail": "The max age in days must be between 1 and 365.",
      "status": 422
    }
  ]
}

At minimum, we will always include the the detail and status members. We may provide more members, as per the spec.

Security

All requests to the AbuseIPDB website and API must run over HTTPS. If a HTTP unsecure protocol is requested, it will be redirected to HTTPS via 302 Found.

While we accept your key as either a query parameter/form parameter or header, the header form is recommended. Why? Although HTTPS will encrypt the entire query string, server logs (like ours) will record them. And your infrastructure may have outgoing logging you are unaware of. You are responsible for account(s) compromised this way.

AbuseIPDB support will never ask you for your API key, nor your account password. We may only ask for your user id.