Block a list of IPs in Cloudflare: an IP list, one rule, and a script that keeps it current
Block thousands of IPs in Cloudflare on any plan: an IP list, one WAF custom rule, and a tested script that refreshes the list from a free feed every six hours.
To block a list of IP addresses in Cloudflare, put them in an IP list and block the list with one WAF custom rule: ip.src in $your_list. Every plan has IP lists, and the Free plan allows one list with up to 10,000 addresses. To keep the list current, a short script can replace its contents through Cloudflare's API on a timer. FFraud's free lists hold 500 to 2,500 addresses each, so they fit a Free plan.
#What does each Cloudflare plan allow?
| Plan | Custom lists | List items, all lists | Custom rules |
|---|---|---|---|
| Free | 1 | 10,000 | 5 |
| Pro | 10 | 10,000 | 20 |
| Business | 10 | 10,000 | 100 |
| Enterprise | 1,000 | 500,000 | 1,000 |
IP lists take single IPv4 and IPv6 addresses, IPv4 ranges from /8 to /32 and IPv6 ranges from /12 to /128, mixed in one list. Cloudflare's own Managed IP Lists come with Enterprise only. On every other plan, the list is yours to fill.
- worst.txt500
- badips.txt2,000
- webattack.txt2,000
- freships.txt2,500
- All four, merged6,314
- Plan limit (Free to Business)10,000
Source: FFraud free lists, read October 25, 2026, 19:03 UTC; Cloudflare WAF documentation
#How do you create the list and the rule?
- In the Cloudflare dashboard, open your account's Lists page under Configurations and create a list of type IP. Name it with lowercase letters, numbers and underscores, up to 50 characters, such as
ffraud_badips. - Add the addresses: type them in, or upload a CSV file with one address per line. The script below fills the list for you instead.
- In the zone you want to protect, create a custom rule with this expression and the action Block:
(ip.src in $ffraud_badips).
One rule covers the whole list, however long it grows. If your own monitoring or office addresses could ever land on a list, put a rule with the action Skip for them above the block rule.
#How do you keep the list current?
Cloudflare's API can replace every item of a list in one call: a PUT on the list's items deletes the old ones and writes the new ones, as one background operation. The script below downloads a FFraud list, builds the items, sends the replace, and waits until Cloudflare reports it complete. It needs only curl, grep, awk and sed.
#!/bin/sh
# Replace a Cloudflare IP list with FFraud's free attacker list, then wait until Cloudflare has applied it.
# A failed download, a short list or an oversized list leaves the Cloudflare list as it is.
set -eu
: "${CF_API_TOKEN:?set CF_API_TOKEN (permission: Account Filter Lists Edit)}"
: "${CF_ACCOUNT_ID:?set CF_ACCOUNT_ID}"
: "${CF_LIST_ID:?set CF_LIST_ID}"
LIST_URL="${LIST_URL:-https://ffraud.com/free/badips.txt}"
API="https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/rules/lists"
tmp=$(mktemp)
trap 'rm -f "$tmp" "$tmp.json"' EXIT
curl -fsS --max-time 30 "$LIST_URL" -o "$tmp"
# One address per line. Addresses hold only hex digits, dots and colons, so no JSON escaping is needed.
grep -E '^([0-9]{1,3}(\.[0-9]{1,3}){3}|[0-9a-fA-F]*:[0-9a-fA-F:]+)$' "$tmp" \
| awk 'BEGIN { printf "[" } { printf "%s{\"ip\":\"%s\",\"comment\":\"FFraud free list\"}", (NR > 1 ? "," : ""), $0 } END { print "]" }' \
> "$tmp.json"
n=$(grep -o '"ip"' "$tmp.json" | wc -l)
if [ "$n" -lt 100 ]; then echo "only $n addresses in the download, list left as it is" >&2; exit 1; fi
if [ "$n" -gt 10000 ]; then echo "$n addresses exceed the 10,000-item limit, list left as it is" >&2; exit 1; fi
op=$(curl -fsS -X PUT "$API/$CF_LIST_ID/items" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" \
--data @"$tmp.json" | sed -n 's/.*"operation_id": *"\([^"]*\)".*/\1/p')
if [ -z "$op" ]; then echo "Cloudflare returned no operation id" >&2; exit 1; fi
i=0
while [ "$i" -lt 30 ]; do
status=$(curl -fsS "$API/bulk_operations/$op" -H "Authorization: Bearer $CF_API_TOKEN" \
| sed -n 's/.*"status": *"\([a-z]*\)".*/\1/p')
case "$status" in
completed) echo "list replaced with $n addresses"; exit 0 ;;
failed) echo "Cloudflare reported the bulk operation as failed" >&2; exit 1 ;;
esac
i=$((i + 1))
sleep 5
done
echo "still $status after 150 seconds; Cloudflare finishes it on its own" >&2
exit 1Create an API token with the permission Account Filter Lists Edit. The account ID sits in the dashboard's URL, and this call prints each list with its ID:
curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/rules/lists" \
-H "Authorization: Bearer $CF_API_TOKEN"FFraud rebuilds its free lists every six hours, so run the script on the same rhythm. One cron line does it, in /etc/cron.d/ffraud-cloudflare-list, with the three variables set in the file above it: 40 */6 * * * root /usr/local/bin/ffraud-cloudflare-list. For a website, set LIST_URL to
What we tested
We ran the script's download, filter and item building on all four FFraud lists on October 25, 2026, and checked every item file with a JSON parser and every address with Python's address parser:
free/badips.txt items 2000 IPv4 2000 IPv6 0 invalid 0 under 10,000: True
free/webattack.txt items 2000 IPv4 2000 IPv6 0 invalid 0 under 10,000: True
sizzling/worst.txt items 500 IPv4 500 IPv6 0 invalid 0 under 10,000: True
sizzling/freships.txt items 2500 IPv4 2473 IPv6 27 invalid 0 under 10,000: True
all four merged, unique: 6314The replace and status calls follow Cloudflare's API documentation; we did not run them against a live account. Run the script once by hand and check the list in the dashboard before you schedule it.
#Should the rule block or challenge?
Block when the list holds attackers of the thing you protect, such as web attackers in front of a website. Choose Managed Challenge for signups, logins and checkouts, where one listed address can carry many real people, such as a mobile carrier's
#What about IP Access rules?
IP Access rules block one address or range per rule, up to 50,000 rules per account on every plan. They suit a handful of addresses you block by hand. For a feed that changes every few hours, a list is the better fit: one rule, and one API call to refresh it.
#Can you load a bigger list?
Up to the plan's item limit: 10,000 below Enterprise, 500,000 on Enterprise. FFraud's full
#Questions people ask
How do I add a large list of IP addresses to block in Cloudflare?
Create an IP list, fill it by CSV upload or with the API's replace call, and block it with one custom rule, ip.src in $your_list. Lists hold up to 10,000 addresses below Enterprise.
Is it possible to upload a list of IP addresses to block?
Yes. A list accepts a CSV file with one address per line, or a JSON array of items through the API.
How do I block an IP range in Cloudflare?
Add the range to an IP list in CIDR form, such as 203.0.113.0/24. Lists take IPv4 ranges from /8 to /32 and IPv6 ranges from /12 to /128.
How do I block multiple IP addresses at once in Cloudflare?
Put them all in one IP list and block the list with one custom rule. Adding or replacing addresses later changes nothing in the rule.
Should I use IP Access rules or a list with a custom rule?
IP Access rules for a few addresses blocked by hand. A list with one custom rule for anything longer, and for any list you refresh from a feed.
To check why one address is on a list, paste it into the free