Shodan is the search engine for Internet-connected devices. Servers, webcams, industrial systems, databases — if it's online, Shodan has indexed it.
Their API gives you programmatic access to this data. The free tier includes search, host lookup, and DNS resolution.
Why Security Pros Use Shodan
A penetration tester was hired to assess a company's external attack surface. Instead of running port scans (which would take hours and trigger alerts), they queried Shodan. In seconds, they had a complete map of every public-facing service — including an exposed MongoDB on port 27017 with no authentication.
The vulnerability had been live for 6 months. Nobody knew.
Get Your Free API Key
- Create account at shodan.io
- Your API key is on your account page
- Free tier: search filters limited, but host lookup is unlimited
Look Up Any IP
\`python
import requests
API_KEY = "your-shodan-api-key"
def lookup_host(ip):
"""Get all known services running on an IP."""
response = requests.get(
f"https://api.shodan.io/shodan/host/{ip}?key={API_KEY}"
)
if response.status_code == 200:
data = response.json()
print(f"IP: {data['ip_str']}")
print(f"Organization: {data.get('org', 'Unknown')}")
print(f"OS: {data.get('os', 'Unknown')}")
print(f"Country: {data.get('country_name', 'Unknown')}")
print(f"Open ports: {data.get('ports', [])}")
for service in data.get("data", []):
port = service["port"]
product = service.get("product", "Unknown")
version = service.get("version", "")
print(f" Port {port}: {product} {version}")
# Check for vulnerabilities
vulns = service.get("vulns", {})
if vulns:
print(f" ⚠ Vulnerabilities: {', '.join(list(vulns.keys())[:5])}")
lookup_host("8.8.8.8")
`\
Search for Exposed Services
\`python
def search_shodan(query, max_results=5):
"""Search Shodan for devices matching a query."""
response = requests.get(
f"https://api.shodan.io/shodan/host/search?key={API_KEY}&query={query}"
)
if response.status_code == 200:
data = response.json()
print(f"Total results: {data['total']}")
for match in data["matches"][:max_results]:
ip = match["ip_str"]
port = match["port"]
org = match.get("org", "Unknown")
country = match.get("location", {}).get("country_name", "Unknown")
print(f"\n{ip}:{port} | {org} | {country}")
# Show banner snippet
banner = match.get("data", "")[:100]
if banner:
print(f" Banner: {banner}")
Find exposed Elasticsearch instances
search_shodan("product:elastic port:9200")
`\
DNS Resolution
Resolve domains to IPs (free, no query credits):
\`python
def resolve_domains(domains):
"""Resolve domain names to IP addresses."""
domain_str = ",".join(domains)
response = requests.get(
f"https://api.shodan.io/dns/resolve?hostnames={domain_str}&key={API_KEY}"
)
for domain, ip in response.json().items():
print(f"{domain} → {ip}")
if ip:
# Now look up the IP for full details
lookup_host(ip)
resolve_domains(["google.com", "github.com", "cloudflare.com"])
`\
Monitor Your Own Infrastructure
\`python
def audit_my_servers(ips):
"""Security audit of your own servers."""
issues = []
for ip in ips:
response = requests.get(
f"https://api.shodan.io/shodan/host/{ip}?key={API_KEY}"
)
if response.status_code != 200:
continue
data = response.json()
# Check for common issues
for service in data.get("data", []):
port = service["port"]
product = service.get("product", "")
# Exposed databases
if port in [27017, 6379, 9200, 5432, 3306]:
issues.append(f"⚠ {ip}:{port} - Database exposed ({product})")
# Unencrypted services
if port in [21, 23, 80] and service.get("ssl") is None:
issues.append(f"⚠ {ip}:{port} - Unencrypted service ({product})")
# Known vulnerabilities
if service.get("vulns"):
vuln_count = len(service["vulns"])
issues.append(f"🔴 {ip}:{port} - {vuln_count} known CVEs")
if issues:
print("SECURITY ISSUES FOUND:")
for issue in issues:
print(f" {issue}")
else:
print("✓ No obvious issues found")
Audit your own servers (ONLY scan IPs you own!)
audit_my_servers(["your.server.ip.here"])
`\
Useful Search Queries
| Query | What it finds |
|---|---|
product:mongodb\ |
MongoDB instances |
port:22 country:US\ |
SSH servers in the US |
http.title:"Dashboard"\ |
Web dashboards |
ssl.cert.issuer.cn:*.gov\ |
Government SSL certs |
vuln:CVE-2021-44228\ |
Log4Shell vulnerable |
has_screenshot:true\ |
Devices with screenshots |
Free Tier Limits
| Feature | Free | Membership ($59) |
|---|---|---|
| Search queries | Limited filters | All filters |
| Host lookups | Unlimited | Unlimited |
| Scan credits | 100/month | Unlimited |
| Results per query | 100 | Unlimited |
| Network monitoring | No | Yes |
Important: Ethics and Legality
Shodan indexes publicly available data. However:
- Only scan/probe systems you own or have permission to test
- Looking up data in Shodan is generally legal (it's public info)
- Acting on that data (accessing exposed databases) without permission is illegal
- Use this for defensive security — protecting your own infrastructure
I write about free APIs for developers and security professionals. More tutorials on my GitHub.
Top comments (0)