DEV Community

Alex Spinov
Alex Spinov

Posted on

Shodan Has a Free API — Discover Internet-Connected Devices Programmatically

A DevOps engineer told me they found their company's unpatched Jenkins server on Shodan — exposed to the entire internet. They patched it within an hour.

Shodan is a search engine for internet-connected devices. It indexes servers, webcams, IoT devices, databases — anything with a public IP. And it has a free API.

Getting Started

Sign up at shodan.io for a free API key. Free tier:

  • 100 query credits/month
  • 100 scan credits/month
  • No filters in search (paid feature)

1. Search for Exposed Services

import requests

API_KEY = 'your_shodan_api_key'  # Free from shodan.io

def shodan_search(query, page=1):
    resp = requests.get(
        'https://api.shodan.io/shodan/host/search',
        params={'key': API_KEY, 'query': query, 'page': page}
    ).json()

    print(f"Total results: {resp.get('total', 0)}")
    for match in resp.get('matches', [])[:5]:
        print(f"  {match['ip_str']:<16} port:{match['port']:<6} {match.get('org','')[:30]}")

    return resp

# Find exposed MongoDB instances
shodan_search('product:mongodb')

# Find Apache servers in a specific country
shodan_search('apache country:US')
Enter fullscreen mode Exit fullscreen mode

2. Check Your Own Infrastructure

def check_ip(ip):
    """Check what Shodan knows about an IP address."""
    resp = requests.get(
        f'https://api.shodan.io/shodan/host/{ip}',
        params={'key': API_KEY}
    )

    if resp.status_code != 200:
        return {'error': resp.json().get('error', 'Unknown')}

    data = resp.json()

    return {
        'ip': ip,
        'org': data.get('org', 'Unknown'),
        'os': data.get('os', 'Unknown'),
        'ports': data.get('ports', []),
        'vulns': data.get('vulns', []),
        'hostnames': data.get('hostnames', []),
        'country': data.get('country_name', 'Unknown')
    }

# Check what's exposed on your server
info = check_ip('8.8.8.8')  # Google DNS as example
print(f"Open ports: {info['ports']}")
print(f"Known vulns: {info['vulns']}")
Enter fullscreen mode Exit fullscreen mode

3. Monitor for New Exposures

def check_org_exposure(org_name):
    """Find all devices associated with an organization."""
    resp = requests.get(
        'https://api.shodan.io/shodan/host/search',
        params={'key': API_KEY, 'query': f'org:"{org_name}"'}
    ).json()

    total = resp.get('total', 0)
    services = {}

    for match in resp.get('matches', []):
        product = match.get('product', 'unknown')
        services[product] = services.get(product, 0) + 1

    print(f"\n{org_name}: {total} exposed devices")
    for service, count in sorted(services.items(), key=lambda x: -x[1])[:10]:
        print(f"  {service}: {count}")

    return {'total': total, 'services': services}
Enter fullscreen mode Exit fullscreen mode

4. Find Vulnerable Services

def find_vulnerable(vuln_id):
    """Search for services with a specific CVE."""
    resp = requests.get(
        'https://api.shodan.io/shodan/host/search',
        params={'key': API_KEY, 'query': f'vuln:{vuln_id}'}
    ).json()

    print(f"Devices with {vuln_id}: {resp.get('total', 0)}")
    for m in resp.get('matches', [])[:5]:
        print(f"  {m['ip_str']:<16} {m.get('org','')[:25]:<26} port:{m['port']}")

# Check for Log4Shell
find_vulnerable('CVE-2021-44228')
Enter fullscreen mode Exit fullscreen mode

5. Quick Stats (No Credits Used)

Some endpoints don't use query credits:

def my_ip():
    """Get your public IP (free, no credits)."""
    return requests.get(
        'https://api.shodan.io/tools/myip',
        params={'key': API_KEY}
    ).text

def api_info():
    """Check your remaining credits."""
    return requests.get(
        'https://api.shodan.io/api-info',
        params={'key': API_KEY}
    ).json()

print(f"My IP: {my_ip()}")
print(f"Credits left: {api_info()['query_credits']}")
Enter fullscreen mode Exit fullscreen mode

Ethical Use

Shodan shows what's already publicly visible. But:

  • Never access systems you don't own
  • Use it to audit YOUR infrastructure
  • Report vulnerabilities you find responsibly
  • Check your company's exposure proactively

Rate Limits

Tier Query Credits Scan Credits
Free 100/month 100/month
Membership ($49) Unlimited 5,120/month
Small Business Unlimited 65,536/month

Free tier is enough for personal security audits.

Combine With


Building a comprehensive free security toolkit. More: GitHub | Technical writing: Spinov001@gmail.com

Top comments (0)