AlienVault Open Threat Exchange (OTX) is the world's largest open threat intelligence community. 200,000+ contributors sharing indicators of compromise (IOCs) in real-time.
Their API is completely free. No usage limits. No premium tier needed.
The Problem It Solves
Threat intelligence feeds are expensive. CrowdStrike, Recorded Future, ThreatConnect — they charge thousands per year. Small security teams can't afford them.
OTX gives you the same type of data: malicious IPs, domains, file hashes, URLs — crowdsourced from 200K+ security researchers worldwide. For free.
Get Your Free API Key
- Sign up at otx.alienvault.com
- Go to Settings → API Integration
- Copy your OTX API Key
Check an IP for Threats
\`python
import requests
API_KEY = "your-otx-api-key"
headers = {"X-OTX-API-KEY": API_KEY}
BASE = "https://otx.alienvault.com/api/v1"
def check_ip(ip):
"""Get threat intelligence for an IP address."""
# General info
r = requests.get(f"{BASE}/indicators/IPv4/{ip}/general", headers=headers, timeout=15)
data = r.json()
pulse_count = data.get("pulse_info", {}).get("count", 0)
country = data.get("country_name", "Unknown")
print(f"IP: {ip}")
print(f"Country: {country}")
print(f"Threat pulses: {pulse_count}")
if pulse_count > 0:
print("⚠ This IP appears in threat intelligence feeds:")
for pulse in data["pulse_info"].get("pulses", [])[:3]:
print(f" └─ {pulse['name']} ({pulse['created']})")
print(f" Tags: {', '.join(pulse.get('tags', [])[:5])}")
else:
print("✓ No known threat associations")
# Reputation
r2 = requests.get(f"{BASE}/indicators/IPv4/{ip}/reputation", headers=headers, timeout=15)
rep = r2.json().get("reputation", {})
if rep:
print(f"Reputation: {rep.get('threat_score', 'N/A')}/7")
check_ip("185.220.101.1")
`\
Check a Domain
\`python
def check_domain(domain):
"""Get threat intelligence for a domain."""
r = requests.get(f"{BASE}/indicators/domain/{domain}/general", headers=headers, timeout=15)
data = r.json()
pulses = data.get("pulse_info", {}).get("count", 0)
print(f"Domain: {domain}")
print(f"Threat pulses: {pulses}")
# Get passive DNS
r2 = requests.get(f"{BASE}/indicators/domain/{domain}/passive_dns", headers=headers, timeout=15)
dns_data = r2.json().get("passive_dns", [])
if dns_data:
print(f"DNS records: {len(dns_data)}")
for record in dns_data[:5]:
print(f" {record.get('address', '?')} — {record.get('record_type', '?')} (seen: {record.get('last', '?')})")
check_domain("example.com")
`\
Check a File Hash
\`python
def check_hash(file_hash):
"""Check if a file hash is associated with malware."""
r = requests.get(f"{BASE}/indicators/file/{file_hash}/general", headers=headers, timeout=15)
data = r.json()
pulses = data.get("pulse_info", {}).get("count", 0)
print(f"Hash: {file_hash[:32]}...")
print(f"Threat pulses: {pulses}")
if pulses > 0:
print("⚠ Known malicious file:")
for p in data["pulse_info"].get("pulses", [])[:3]:
print(f" └─ {p['name']}")
Check a known malicious hash (EICAR test file)
check_hash("275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f")
`\
Subscribe to Threat Pulses
OTX organizes threat data into "Pulses" — curated collections of IOCs:
\`python
def get_latest_pulses(limit=5):
"""Get the latest threat intelligence pulses."""
r = requests.get(
f"{BASE}/pulses/subscribed",
headers=headers,
params={"limit": limit, "page": 1},
timeout=15
)
data = r.json()
for pulse in data.get("results", []):
name = pulse["name"]
created = pulse["created"]
indicators = len(pulse.get("indicators", []))
tags = ", ".join(pulse.get("tags", [])[:4])
print(f"\n📡 {name}")
print(f" Created: {created}")
print(f" Indicators: {indicators}")
print(f" Tags: {tags}")
get_latest_pulses()
`\
Build a Threat Feed Aggregator
\`python
def aggregate_iocs(pulse_ids):
"""Aggregate IOCs from multiple pulses into a single feed."""
all_iocs = {"IPv4": [], "domain": [], "FileHash-SHA256": [], "URL": []}
for pid in pulse_ids:
r = requests.get(f"{BASE}/pulses/{pid}/indicators", headers=headers, timeout=15)
for indicator in r.json().get("results", []):
ioc_type = indicator["type"]
if ioc_type in all_iocs:
all_iocs[ioc_type].append(indicator["indicator"])
for ioc_type, values in all_iocs.items():
if values:
unique = list(set(values))
print(f"\n{ioc_type}: {len(unique)} unique indicators")
for v in unique[:3]:
print(f" {v}")
Aggregate IOCs from subscribed pulses
aggregate_iocs(["pulse-id-1", "pulse-id-2"])
`\
What You Can Build
- SIEM integration — enrich alerts with OTX threat data
- Email gateway — check sender IPs and URLs against OTX
- Automated blocklists — generate IP/domain blocklists from pulses
- Threat dashboard — visualize current threat landscape
- Incident response — bulk-check IOCs from breach investigations
No Rate Limits
OTX has no published rate limits for the API. They ask for reasonable use, but there's no hard cap — making it ideal for integration into production security tools.
More free security APIs and tools on my GitHub.
Top comments (0)