---
name: crowdsec-cti-api-ingestion
description: "How to get CrowdSec CTI API data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Load a CrowdSec CTI IP report into pandas and Parquet

Source entry: https://signal-lab-jet.vercel.app/datasets/crowdsec-cti-api
Provider: https://docs.crowdsec.net/u/cti_api/intro/
Checked against the provider's documentation: 2026-11-01

## Access
- Create a CrowdSec account and a free Community CTI API key.
- Store the key in CROWDSEC_CTI_API_KEY; the Community allowance is 120 IP queries per month.

## Request
```bash
curl -H "x-api-key: $CROWDSEC_CTI_API_KEY" 'https://cti.api.crowdsec.net/v2/smoke/1.2.3.4'
```

## Format
JSON IP report with reputation and confidence fields plus network, location, behavior, attack, score, CVE and history context when available.

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""CrowdSec CTI smoke IP report -> pandas -> Parquet. Needs a free API key."""
import json
import os
import requests
import pandas as pd

URL = "https://cti.api.crowdsec.net/v2/smoke/1.2.3.4"
headers = {"x-api-key": os.environ["CROWDSEC_CTI_API_KEY"]}
r = requests.get(URL, headers=headers, timeout=60)
r.raise_for_status()
payload = r.json()
df = pd.json_normalize(payload, sep=".")
for column in df.columns:
    if df[column].map(lambda value: isinstance(value, (list, dict))).any():
        df[column] = df[column].map(lambda value: json.dumps(value) if isinstance(value, (list, dict)) else value)
df.to_parquet("crowdsec_cti_ip.parquet", index=False)
print(len(df), "IP report", payload.get("ip", "1.2.3.4"), payload.get("reputation"))
```
Not run: it needs a free API key.

## Limits
- Rate limit: 120 queries per month on the Community key; no per-second limit is stated.
- Unused monthly quota does not roll over.
- Bulk Lucene-style API search and offline replicas are not included with self-service Community access.

## Quirks
- The smoke endpoint and reserved example address exercise the response shape without directing the script to a listed hostile host.
- Treat reputation and scores as time-dependent observations; absent context is not a safe-address finding.
- Nested behaviors, attacks and CVE fields are JSON-encoded before Parquet export.

## Terms and attribution
- Community access is feature-limited and does not authorize use to protect third-party environments.
- The EULA prohibits distributing or marketing CrowdSec assets; commercial resale requires separate rights.
- Terms page: https://booking.crowdsec.net/hubfs/EULA%20Crowdsec%20v2%20.pdf?hsLang=en

## Sources
- https://docs.crowdsec.net/u/cti_api/enrichment_api/: "All requests require a CTI API key passed in the x-api-key header."
- https://docs.crowdsec.net/u/console/ip_reputation/api_keys/: "Community Plan Free Key - 120 / month · Testing integrations, personal servers, ad-hoc lookups"
- https://docs.crowdsec.net/u/cti_api/intro/: "CrowdSec tracks malicious IPs across hundreds of thousands of real deployments worldwide."
- https://booking.crowdsec.net/hubfs/EULA%20Crowdsec%20v2%20.pdf?hsLang=en: "All rights not expressly granted to the End User are prohibited."

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab-jet.vercel.app/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
