Observed since 20 Oct, 17:46 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Unofficial typed Python client for the AbuseIPDB API v2
Typed, synchronous Python client for AbuseIPDB API v2. This is a personal, unofficial port created by William Friend for Python packaging and release practice. It follows architecture and behavior of official AbuseIPDB/laravel 2.0.1, but is not produced, endorsed, or supported by AbuseIPDB.
Distribution name is abuseipdb-python-sdk; import namespace remains future-friendly abuseipdb.
python -m pip install abuseipdb-python-sdk
Python 3.10 or newer is required.
export ABUSEIPDB_API_KEY="your-key"
from abuseipdb import AbuseIPDB
client = AbuseIPDB() # reads ABUSEIPDB_API_KEY
client = AbuseIPDB(
api_key="your-key", # takes precedence over environment
timeout=10.0,
)
Use client as context manager, or call client.close() when done. Every request sends Key, correct Accept, and an X-Request-Source identifying Python and SDK versions.
with AbuseIPDB() as client:
result = client.check("8.8.8.8", max_age_in_days=90, verbose=True)
print(result.ip_address, result.abuse_confidence_score)
for report in result.reports:
print(report.reported_at, report.categories)
Reporting changes production data. Verify input and category choice.
from abuseipdb import AbuseCategory, AbuseIPDB
with AbuseIPDB() as client:
result = client.report(
"203.0.113.10",
categories=[AbuseCategory.BRUTE_FORCE, AbuseCategory.SSH],
comment="Repeated SSH authentication attempts",
)
One raw ID (categories=18) or iterable of enum/raw IDs works. Optional timestamp must be datetime.datetime and serializes using ISO 8601.
with AbuseIPDB() as client:
page = client.reports("203.0.113.10", max_age_in_days=30, page=1, per_page=25)
print(page.total, page.count, page.last_page)
for report in page.results:
print(report.reported_at)
with AbuseIPDB() as client:
result = client.blacklist(
confidence_minimum=90,
limit=10000,
only_countries=["US", "CA"],
except_countries=None,
ip_version=6,
)
for entry in result.blacklisted_ips:
print(entry.ip_address, entry.last_reported_at)
Plaintext is first-class and does not attempt JSON decoding:
with AbuseIPDB() as client:
result = client.blacklist(confidence_minimum=90, plaintext=True)
for ip in result.addresses:
print(ip)
IPv4 and IPv6 CIDR strings pass through URL encoding correctly.
with AbuseIPDB() as client:
result = client.check_block("2001:db8::/64", max_age_in_days=30)
for address in result.reported_addresses:
print(address.ip_address, address.num_reports)
bulk_report accepts CSV contents—not a path—matching Laravel 2.0.1's actual method contract. SDK uploads them as multipart field csv, filename report.csv.
csv_contents = "IP,Categories,ReportDate,Comment\n203.0.113.10,18,,Brute force\n"
with AbuseIPDB() as client:
result = client.bulk_report(csv_contents)
print(result.saved_reports, result.invalid_reports)
This deletes only your account's reports for given address.
with AbuseIPDB() as client:
result = client.clear_address("2001:db8::10")
print(result.num_reports_deleted)
AbuseCategory contains all IDs 1–23 from Laravel 2.0.1. CATEGORIES exposes Laravel-compatible display-name mapping.
from abuseipdb import AbuseCategory, CATEGORIES
assert AbuseCategory.PORT_SCAN == 14
assert CATEGORIES["SSH"] == 22
API camelCase becomes public snake_case: abuseConfidenceScore becomes abuse_confidence_score. Top-level types are AbuseResponse, CheckResponse, ReportResponse, ReportsPaginatedResponse, BlacklistResponse, BlacklistPlaintextResponse, BulkReportResponse, CheckBlockResponse, and ClearAddressResponse. Nested types are ReportInfo, BlacklistedIP, BulkInvalidReport, and CheckBlockIP.
All responses retain status_code, selected response headers, and raw_response. ISO dates become timezone-aware datetime values. Optional fields use None; nested collections use immutable tuples.
All SDK exceptions derive from AbuseIPDBError:
InvalidParameterError: Laravel-compatible client validation failure.MissingAPIKeyError: no explicit or environment API key.PaymentRequiredError: HTTP 402.UnprocessableContentError: HTTP 422.TooManyRequestsError: HTTP 429.UnconventionalAPIError: any other unsuccessful HTTP status.HTTP errors expose status_code, detail, and original response. Recognizable *Exception aliases are available for Laravel migration.
Laravel's automatic Symfony exception hook has no generic Python equivalent. Optional abuseipdb.reporters.report_suspicious_operation accepts address and request parameter mapping supplied by your framework, reports category 21, and suppresses SDK failures like upstream helper. Wire it into your framework explicitly; never include secrets in submitted parameters.
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
ruff check .
ruff format --check .
pytest --cov
mypy src
python -m build
twine check dist/*
Unit tests are offline; mocked write operations never contact production. See RELEASE.md for personal manual release practice and PORTING_NOTES.md for exact Laravel mappings and discrepancies.
From repository root:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
pytest --cov
Editable installation means imports use current src/ code; reinstall is unnecessary after edits. To test exact built wheel instead:
rm -rf dist build
python -m build
python -m venv /tmp/abuseipdb-local-wheel
/tmp/abuseipdb-local-wheel/bin/python -m pip install dist/abuseipdb_python_sdk-0.1.0-py3-none-any.whl
cd /tmp
/tmp/abuseipdb-local-wheel/bin/python -c "import abuseipdb; print(abuseipdb.__version__)"
VS Code: open Command Palette → Tasks: Run Task. Use Test: pytest or Quality: all automatic checks from .vscode/tasks.json.
Normal pytest never contacts AbuseIPDB. Live runner calls every endpoint, including destructive report, bulk-report, and clear-address. Use two different real abusive public IPs you are authorized to report; cleanup deletes your account's reports for those addresses. Do not use documentation/reserved IPs for writes.
Keep API key in shell environment, never source control:
export ABUSEIPDB_API_KEY="your-real-key"
export ABUSEIPDB_E2E_CHECK_IP="8.8.8.8"
export ABUSEIPDB_E2E_REPORT_IP="real-abusive-public-ip-1"
export ABUSEIPDB_E2E_BULK_IP="real-abusive-public-ip-2"
export ABUSEIPDB_E2E_NETWORK="8.8.8.0/24"
python tests/manual/e2e.py --allow-writes
Production API is automatic. Developers testing against local server can override it explicitly:
export ABUSEIPDB_URL="http://abuseipdb.localhost/api/v2"
python tests/manual/e2e.py --allow-writes
Constructor override also works: AbuseIPDB(base_url="http://abuseipdb.localhost/api/v2"). Explicit constructor value wins over developer environment override.
Runner prints [PASS] or [FAIL], typed output/error body for every call, and final count. It continues after failures so one run shows whole API state. VS Code task Manual: live API E2E (WRITES REPORTS) prompts for key/addresses without saving them.
API behavior is documented by AbuseIPDB API v2. Architecture is based on official AbuseIPDB Laravel SDK. This unofficial project uses MIT license consistent with upstream.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 1 Aug 2026 | 8 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 17:46 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:5709d82d9b7cd6762396833799fe7ffec14ddc99264cab31d91c1cd431a21984