Shodan turns 17 this year, and it still does one thing better than almost any other tool in a security team’s kit: it tells you what the internet already knows about your infrastructure before an attacker finds out first. Type a query into Shodan and you get a live inventory of exposed routers, industrial controllers, misconfigured databases, and forgotten servers, indexed the same way Google indexes web pages, except the “pages” here are open ports and service banners.
This tutorial walks through setting up Shodan for real attack surface reconnaissance work: creating an account, picking the right pricing tier, installing the command-line interface, writing filtered queries (often called “dorks”), wiring up continuous monitoring, and feeding results into Nmap, nuclei, and a SIEM. By the end you will have a repeatable workflow you can run against your own organization’s IP ranges on a schedule, plus a clear sense of where the legal and ethical lines sit.
What Shodan Actually Does and Why It Matters in 2026
Shodan is a search engine for internet-connected devices rather than web pages. Where Google crawls hyperlinks, Shodan’s scanners connect to open ports across the public IPv4 (and increasingly IPv6) address space, grab the service banner that comes back, and index it. That banner might identify an OpenSSH version, a MongoDB instance with no authentication, a building’s HVAC controller, or a webcam still running factory-default credentials. Security teams use that index to answer a question that is otherwise hard to answer from the inside: what does our organization look like from the outside, right now, to anyone with a browser?
That framing matters more in 2026 than it did a few years ago. Cloud sprawl, shadow IT, and OT/ICS devices bridged onto corporate networks have made “what’s actually exposed” a moving target for most organizations. Shodan’s continuous scanning approach means an asset that was locked down last quarter but got re-exposed by a misconfigured load balancer last week will usually show up in a fresh query, often faster than an internal asset inventory catches it. That is the core pitch behind attack surface management as a category, and Shodan remains one of the tools that popularized it.
Security researchers also lean on Shodan to study patterns at scale: exposed industrial control systems and SCADA gear reachable over protocols like Modbus, unauthenticated Elasticsearch and MongoDB clusters leaking records, and consumer IoT devices such as webcams and DVRs sitting wide open on residential and small-business networks. None of that requires exploiting anything. Shodan only surfaces what a device already broadcasts to anyone who connects to it, which is also why the tool sits in a legal gray zone that this tutorial covers later on.
Real-World Use Cases: What Security Teams Actually Search For
Before diving into setup, it helps to see the shape of queries security teams actually run in production, because the abstract “search for exposed devices” pitch does not tell you much until you see the patterns. Four categories cover most real-world Shodan usage.
Industrial control systems and SCADA exposure is the category that gets the most attention in security research, because the consequences of a misconfigured PLC or HMI reaching the public internet are physical, not just data-related. Researchers commonly query for Modbus (`port:502`), a widely used industrial protocol, or search by `product:` strings tied to specific PLC vendors. A query like `port:502 country:US` on its own tends to surface hundreds of devices, and cross-referencing that against `tag:ics` narrows results to Shodan’s own industrial classification. Utilities, manufacturing plants, and water treatment facilities have all turned up in these sweeps over the years, usually because a vendor’s remote-support VPN got misconfigured rather than because anyone intended for the device to be internet-facing.
Exposed databases are the second major category, and the pattern is almost always the same: a developer spins up MongoDB, Elasticsearch, Redis, or a similar data store for testing, binds it to 0.0.0.0 instead of localhost, and forgets to add authentication before the instance goes anywhere near a public cloud subnet. The query `product:”MongoDB” port:27017 -authentication` from Step 4 is a direct, repeatable way to check whether your own cloud estate has made that mistake. The same pattern applies to Elasticsearch on port 9200 and Redis on port 6379, both worth adding to a standing query rotation if your organization runs any of them.
Consumer and small-business IoT, webcams, DVRs, and network video recorders in particular, make up the third category and are the most frequently cited in general-audience coverage of Shodan, largely because the results are visual and easy to understand without a security background. A query like `product:”IP Camera” country:US` returns thousands of results, many still running factory-default credentials. This category matters less for enterprise attack surface work and more as a reminder of why default-credential hygiene belongs in every vendor security questionnaire your organization sends out.
Cloud infrastructure drift is the fourth category and the one most directly relevant to the workflow this tutorial builds. Load balancers, Kubernetes API servers, admin panels, and internal tools occasionally get exposed when a security group rule is loosened for debugging and never reverted. A `net:` query scoped to your own published CIDR ranges, run on a schedule, is the most direct way to catch this category before it becomes an incident rather than after.
Prerequisites and Versions
You do not need specialized hardware for this tutorial, but you do need a few things lined up before Step 1.
- A Shodan account (free tier works for the early steps; paid tier needed for filters and monitoring)
- Python 3.9 or newer, with pip available on your PATH
- A terminal on Linux, macOS, or Windows (WSL2 recommended on Windows)
- Nmap installed locally for the integration step (version 7.9x or newer)
- nuclei installed if you plan to chase the vulnerability-scanning workflow (ProjectDiscovery’s Go-based scanner)
- Written authorization to scan or monitor the IP ranges you plan to query results against, if that range belongs to an employer or client
- Basic comfort with command-line flags and JSON output
One clarification up front: you do not need authorization to run search queries against Shodan’s existing index, because you are querying data Shodan already collected through its own scanning, not scanning targets yourself. You do need authorization before you actively scan, probe, or exploit anything you find, and before you use Shodan’s on-demand scan credits against a network segment you do not own or have permission to test.
Step 1: Create a Shodan Account and Pick a Plan
Head to shodan.io and register with an email address. The free tier gets you a taste of the platform: capped results, no filters, and a hard rate limit, which is fine for kicking the tires but too thin for real reconnaissance work. Shodan’s 2026 pricing structure breaks down into five tiers, summarized below.
| Plan | Price | Query credits/month | Scan credits/month | Best for |
|---|---|---|---|---|
| Free | $0 | Very limited, no filters | Minimal | First-time exploration |
| Membership | $49 one-time | 100 | 100 | Individual learners, students |
| Freelancer | $69/month | 10,000 | 5,120 | Independent consultants, small recon jobs |
| Small Business | $359/month | 200,000 | 65,536 | In-house security teams, vuln filter access |
| Corporate | $1,099/month | Unlimited | 327,680 | Enterprise ASM programs |
The Membership tier is a one-time $49 payment (Shodan runs periodic sales that drop it lower) and unlocks full search filters plus basic API access, but with just 100 query and scan credits a month, which burns fast once you start scripting queries. For a solo practitioner running periodic recon, Freelancer at $69/month is usually the practical floor. The `vuln:` filter, which cross-references CVEs against indexed banners, requires at least Small Business. Enterprise pricing is negotiated directly with Shodan’s sales team and adds a full data license for bulk ingestion into internal platforms.
For this tutorial, a Membership or Freelancer account is enough to follow every step. Note your API key from the account dashboard immediately after signup; you will need it in Step 3.
Step 2: Learn the Web Interface Before Scripting Anything
Resist the urge to jump straight to the API. The web interface at shodan.io/search teaches you the filter syntax faster than reading documentation cold, because you see results update in real time as you add or remove filters. Try a basic query first:
apache country:US port:80
That returns Apache servers on port 80 located in the United States. Now narrow it to a specific organization you are authorized to assess:
org:"Your Company Name" net:203.0.113.0/24
The `net:` filter restricts results to a CIDR range, which is the query you will run most often once you move into monitoring your own address space. Spend fifteen minutes clicking through the “Explore” tab and the filter reference in Shodan’s documentation before moving to the CLI. You will save yourself a lot of trial and error later.
Step 3: Install and Initialize the Shodan CLI
Shodan ships an official command-line client as a Python package, which is what you will script against for repeatable, scheduled recon runs. Install it with pip:
pip install -U --user shodan
Confirm the install worked:
shodan version
Then link the CLI to your account using the API key from Step 1:
shodan init YOUR_API_KEY
If that command returns successfully, run a quick sanity check against your own account status:
shodan info
This prints your remaining query credits, scan credits, and plan name. Keep an eye on this output as you build out scripted queries in later steps, since it is easy to burn through a Freelancer plan’s monthly allotment faster than expected once you start looping over multiple CIDR ranges.
Step 4: Master the Core Filter Syntax
Shodan’s filters function like Google dorks for infrastructure. Combining them is where the tool becomes genuinely useful for attack surface work rather than idle browsing. The table below covers the filters you will use in almost every real query.
| Filter | Purpose | Example |
|---|---|---|
| port: | Restrict to a TCP/UDP port | port:22 |
| country: | Restrict to a 2-letter ISO country code | country:DE |
| org: | Filter by organization/ASN owner | org:”Example Corp” |
| net: | Filter by CIDR range | net:198.51.100.0/24 |
| product: | Filter by banner-identified software | product:”MongoDB” |
| vuln: | Match services against a known CVE (Small Business+) | vuln:CVE-2023-22965 |
| hostname: | Match a domain or subdomain string | hostname:example.com |
Chain filters together with spaces, which Shodan treats as an implicit AND:
product:"MongoDB" port:27017 -authentication
The leading dash excludes results that contain the word “authentication” in the banner, a common trick for surfacing genuinely unauthenticated instances rather than ones that merely mention the word. This exact query pattern is one of the most cited examples of how researchers have used Shodan to locate exposed NoSQL databases leaking records, and it is worth running against your own cloud estate before someone else does.
Step 5: Run Your First Scripted Query From the CLI
Now put the filters to work from the terminal instead of the browser. This command searches for SSH servers inside a CIDR block you are authorized to assess and dumps the output as JSON:
shodan search --fields ip_str,port,org,hostnames "net:203.0.113.0/24 port:22" > ssh_exposure.json
Each search query consumes one query credit from your plan, regardless of how many results come back. For host-level detail on a single address, use the host lookup command instead, which also costs one credit:
shodan host 203.0.113.45
That returns every open port Shodan has recorded for the address, the banners collected on each, geolocation data, and any CVE matches Shodan has associated with the detected software versions. This is the single most useful command for a “what does this one IP look like from outside” check during an incident or a pre-audit sweep.
Step 6: Build a Repeatable Attack Surface Sweep Script
A one-off query is a snapshot. A script you can rerun weekly is an actual process. Here is a minimal Python script using the official `shodan` library that loops over a list of your organization’s CIDR ranges and flags anything with an associated CVE:
import shodan
import csv
API_KEY = "YOUR_API_KEY"
RANGES = ["203.0.113.0/24", "198.51.100.0/25"]
api = shodan.Shodan(API_KEY)
rows = []
for cidr in RANGES:
try:
results = api.search(f"net:{cidr}")
for match in results["matches"]:
vulns = match.get("vulns", {})
rows.append({
"ip": match["ip_str"],
"port": match["port"],
"product": match.get("product", ""),
"vulns": ";".join(vulns.keys()) if vulns else "",
})
except shodan.APIError as e:
print(f"Error querying {cidr}: {e}")
with open("attack_surface_report.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["ip", "port", "product", "vulns"])
writer.writeheader()
writer.writerows(rows)
print(f"Wrote {len(rows)} rows to attack_surface_report.csv")
Run this on a cron job (weekly is a reasonable cadence for most organizations) and diff the output against the previous run. New rows mean something changed on your perimeter, which is exactly the signal an ASM process is supposed to catch before an attacker does.
Step 7: Set Up Shodan Monitor for Continuous Alerts
Scripted sweeps work, but Shodan Monitor removes the scheduling burden entirely by watching your declared IP ranges continuously and alerting when something changes. To configure it, log into the web dashboard, navigate to Monitor, and add your organization’s CIDR ranges or individual IPs. Monitored IP quotas scale with your plan tier: 5,120 IPs on Freelancer, up to 327,680 on Corporate.
Once ranges are added, Monitor tracks new open ports, banner changes, and newly matched CVEs against those assets, and can push alerts via email or webhook. This is the piece that turns Shodan from a research tool into an operational control: instead of remembering to rerun a script, you get notified the moment a load balancer misconfiguration exposes an admin panel that was supposed to stay internal.
Step 8: Pull Results Into Nmap for Deeper Verification
Shodan’s data comes from periodic internet-wide scans, which means it can lag reality by hours or days. Before acting on a finding, verify it with a live Nmap scan against the specific host. Extract IPs from your CSV report and feed them straight into Nmap:
cut -d, -f1 attack_surface_report.csv | tail -n +2 | sort -u > targets.txt
nmap -sV -Pn -iL targets.txt -oN verification_scan.txt
The `-sV` flag grabs service versions directly from the live host rather than relying on Shodan’s cached banner, and `-Pn` skips host discovery pings, which many hardened hosts block anyway. Compare the fresh Nmap output against what Shodan reported; discrepancies usually mean either the service was patched since Shodan’s last scan, or a firewall rule changed. Both outcomes are useful signal.
Step 9: Chain Into nuclei for Vulnerability Confirmation
Shodan’s `vuln:` filter tells you a CVE was matched against a banner, but banner-matching produces false positives. Confirmed critical findings should feed into the same patch workflow your team uses for CISA KEV entries. ProjectDiscovery’s nuclei scanner runs actual proof-of-concept checks against live targets, which is the natural next step for confirming a finding before it goes into a report. Point nuclei at the same target list:
nuclei -l targets.txt -t cves/ -severity critical,high -o confirmed_vulns.txt
This workflow, Shodan for discovery, Nmap for live verification, nuclei for exploit-level confirmation, mirrors how OSINT-driven bug bounty researchers and internal red teams using tools like Burp Suite typically chain reconnaissance into deeper testing. Each stage filters out noise before the next, so what lands in your final report is confirmed rather than speculative.
Step 10: Feed Confirmed Findings Into Your SIEM
A standalone CSV report is useful once. A feed into your SIEM or ASM dashboard makes the process durable. If you are running Wazuh, an osquery endpoint monitoring deployment, or a commercial SIEM, the pattern is the same: use Shodan’s API output to enrich existing asset records with external exposure context, then alert when a previously-unseen exposed port shows up against an asset your internal inventory already tracks. Many ASM platforms and enterprise Shodan customers automate this with the Enterprise Data License, which supports bulk ingestion rather than one-off API calls.
If you already have a vulnerability scanning workflow in place, Shodan output slots in as an external-perspective input alongside internal scan data, which closes a blind spot most internal-only scanners have: they cannot see what your network looks like from outside your own firewall.
Understanding Shodan’s Query Credit Economics
Credit consumption is the single most common source of confusion for teams adopting Shodan, so it is worth breaking down precisely how the accounting works before you build automation around it. Every search query, regardless of how many results it returns, costs exactly one query credit. Running `shodan search “net:203.0.113.0/24″` against a range with 500 live hosts costs the same one credit as a query against a range with two hosts. This matters for how you structure sweeps: broad queries with tight filters are almost always more credit-efficient than looping over individual IPs one at a time.
Host lookups work differently. The `shodan host ` command also costs one credit per call, but unlike a search, it returns everything Shodan knows about that single address across all ports and historical banners, so it is the right tool when you already know the IP and want full detail, not when you are trying to discover unknown assets across a range.
Scan credits are separate from query credits and apply only when you explicitly request Shodan perform an on-demand scan of a target rather than search its existing index. This is the feature that requires the strictest authorization discipline, because you are directly instructing Shodan’s infrastructure to probe a specific address, which is functionally identical to running the scan yourself. A Freelancer plan’s 5,120 monthly scan credits sound generous, but a script that loops over a /24 subnet (256 addresses) and mistakenly calls the scan API instead of the search API burns through a meaningful chunk of that allotment in a single run.
Monitor credits, the quota governing how many IPs Shodan Monitor can continuously watch, are consumed differently again: they are not a per-query cost but a standing allocation. Once you add an IP to Monitor, it occupies one slot in your quota until you remove it, regardless of how many alerts it generates. For most mid-sized organizations, mapping your actual public IP inventory against the Freelancer tier’s 5,120-IP Monitor quota reveals that Freelancer covers small and mid-sized networks comfortably, while anything approaching enterprise scale needs Small Business or Corporate.
A practical budgeting exercise before committing to a plan: count your organization’s total publicly routable IPs, estimate how many distinct `net:` sweeps you would realistically run per month (weekly full sweeps plus occasional ad hoc investigation queries is a reasonable baseline), and multiply by roughly 1 credit per sweep per range. Most mid-sized organizations land comfortably inside Freelancer’s 10,000 monthly query credits unless they are running per-IP host lookups at scale, in which case Small Business’s 200,000 credits provides meaningfully more headroom.
Step 11: Compare Shodan Against Censys and ZoomEye
Shodan is not the only device search engine, and picking the right one (or running more than one) depends on what you are hunting for. The comparison below reflects how the three tools are commonly positioned in 2026.
| Tool | Primary strength | Entry pricing | Best fit |
|---|---|---|---|
| Shodan | Device banners, ports, ICS/IoT coverage | $49 one-time / $69 per month | Exposed devices, OT/ICS recon |
| Censys | Certificate and host-level graph, TLS data | Free tier with limited quota; paid tiers scale by volume | Web infrastructure and certificate OSINT |
| ZoomEye | Similar device indexing model, different geographic dataset emphasis | Freemium, cheaper entry | Budget-conscious teams needing a second data source |
In practice, mature security programs often run Shodan and Censys side by side rather than picking one, because Shodan’s banner-first approach and Censys’s certificate-first approach surface different subsets of the same attack surface. If budget only allows one tool, Shodan’s ICS/IoT coverage and the maturity of its filter syntax make it the more commonly adopted starting point for teams doing device-focused reconnaissance.
Step 12: Document Your Legal and Ethical Boundaries
Before this workflow goes into production, write down the rules your team follows, because Shodan sits close enough to offensive tooling that ambiguity here causes real problems later. The guidance that has held up across 2026 discussions of Shodan use boils down to a few points.
- Searching Shodan’s existing index is generally lawful, since you are reading data Shodan already collected from publicly reachable services, not accessing anything yourself.
- Attempting to authenticate into a system you found through Shodan, even with default or leaked credentials, crosses into unauthorized access under most computer-misuse laws.
- On-demand scan credits should only ever target IP ranges you own or have documented authorization to test.
- If you discover an exposed database, ICS device, or webcam belonging to a third party, route it through your organization’s incident response plan and responsible disclosure channel rather than downloading, streaming, or publicizing what you found.
- Corporate use should sit inside an approved security assessment or audit program, not an individual analyst’s personal initiative.
Put these rules in your team’s runbook alongside the scripts from Step 6, so anyone running the sweep later inherits the same boundaries you set here.
Common Pitfalls
A handful of mistakes account for most of the frustration people run into when they first script against Shodan.
- Burning credits with unfiltered queries. A bare search with no `net:` or `org:` filter returns global results and chews through your monthly quota fast. Always scope queries to a specific range before running them in a loop.
- Treating banner data as ground truth. Shodan’s scan cadence means a banner can be stale by days or weeks. Always verify with a live Nmap scan before escalating a finding.
- Forgetting the `vuln:` filter requires a paid tier. Free and base Membership accounts silently return no results for `vuln:` queries rather than an obvious error, which confuses first-time users.
- Scanning ranges without authorization. Using on-demand scan credits against IPs you do not own is the fastest way to trigger an abuse complaint against your account.
- Ignoring rate limits in scripts. Non-enterprise API keys are capped around 1 request per second; scripts that hammer the API faster than that will start failing silently or get temporarily throttled.
- Assuming index size equals real-time truth. Shodan does not claim a fixed, continuously updated device count; treat any “X million devices indexed” figure as a rough, moving approximation rather than a live counter.
- Skipping Shodan Monitor setup. Relying purely on manual searches means you only catch new exposure when you remember to look, which defeats the purpose of continuous attack surface management.
Troubleshooting
Here are the issues most likely to come up while working through this setup, and the fix for each.
- `shodan init` returns an authentication error. Double-check you copied the full API key from account.shodan.io without leading or trailing whitespace, and confirm the account is fully verified via email.
- CLI installs but the `shodan` command is not found. The pip `–user` flag installs to a user-local bin directory that may not be on your PATH; add it manually or reinstall inside a virtual environment.
- Queries return zero results for a range you know is populated. Confirm the CIDR notation is correct and that Shodan has actually scanned that range recently; some ranges, especially newly allocated ones, take time to appear in the index.
- `vuln:` filter returns nothing even on a paid plan. Confirm your plan tier explicitly includes vulnerability search; Freelancer does not include it, only Small Business and above.
- API calls fail with a 429 or rate-limit error. Add a short sleep between requests in your script; non-enterprise keys are limited to roughly one request per second.
- Monitor is not alerting on new exposure. Verify the specific IP or range was actually added under the Monitor tab, not just searched; monitoring is opt-in per asset, not automatic for anything you have queried.
- Nmap results do not match Shodan’s banner. This is expected and not a bug; treat it as confirmation that something changed since Shodan’s last scan pass, and trust the fresher Nmap data.
- Script exhausts your monthly query credits mid-run. Check remaining credits with `shodan info` before large batch runs, and consider caching results locally to avoid re-querying unchanged ranges every cycle.
Running the Sweep in Docker for Portable Automation
If your team already runs scheduled jobs through containers rather than bare cron on a VM, packaging the sweep script from Step 6 into a small Docker image keeps the dependency footprint isolated and makes the job portable across CI runners, Kubernetes CronJobs, or a scheduled Lambda container. A minimal Dockerfile looks like this:
FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends nmap
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir shodan
WORKDIR /app
COPY sweep.py .
ENTRYPOINT ["python", "sweep.py"]
Build and run it, passing the API key as an environment variable rather than baking it into the image:
docker build -t shodan-sweep .
docker run --rm -e SHODAN_API_KEY="your_key_here" -v "$(pwd)/reports:/app/reports" shodan-sweep
Mounting a local `reports` directory as a volume persists the CSV output between container runs, which matters for the diff-against-previous-run logic in the complete project script later in this tutorial. If you are running this inside Kubernetes, a CronJob manifest with the same image and a `schedule: “0 6 * * 1″` field reproduces the weekly cadence without needing a dedicated always-on VM just to host a cron daemon.
Containerizing the sweep also makes it easier to hand off between team members. A colleague picking up the on-call rotation does not need Python or the Shodan CLI installed locally; they only need Docker and the API key, which shrinks the onboarding friction for a process that is otherwise easy to let quietly stop running once the person who set it up moves to a different project.
Advanced Tips
Once the core workflow is running reliably, a few refinements make it more useful for an ongoing security program rather than a one-time exercise.
Use the `hostname:` filter alongside `net:` when your organization’s assets sit behind shared cloud infrastructure. A raw CIDR sweep on a shared hosting range returns a lot of noise that does not belong to you; anchoring on your own domain names filters that out. Combine `product:` with `-tag:self-signed` when you specifically want to find services with valid, properly configured certificates versus ones an engineer spun up quickly and forgot to harden.
For ICS/OT environments, build a dedicated query set around industrial protocols rather than reusing your general web-facing sweep. A query like `port:502 country:US` targets Modbus, a common industrial protocol, and is worth running quarterly against your OT network’s public-facing edge even if you believe it is fully air-gapped; air gaps fail more often than teams expect, and Shodan is a cheap way to catch the failure.
If you are running Shodan queries as part of a bug bounty or authorized penetration test, keep a query log alongside your findings. Reviewers and clients increasingly expect OSINT methodology documentation, and a saved list of the exact Shodan filters you ran makes the reconnaissance phase of your report reproducible rather than a vague “we used Shodan” line.
Finally, budget your credits deliberately across the month rather than front-loading a single large sweep. Spreading queries across a scheduled cadence, say a rolling subset of your IP ranges each day rather than the full estate all at once, keeps you within a Freelancer plan’s quota while still achieving full coverage over a week or two.
Complete Working Project: Weekly Attack Surface Report
Putting every step together, here is a complete, minimal project you can drop into a cron job or CI pipeline to generate a weekly attack surface report, verify findings, and flag anything new since the last run.
#!/usr/bin/env python3
"""Weekly Shodan attack surface sweep with Nmap verification."""
import shodan
import subprocess
import csv
import os
API_KEY = os.environ["SHODAN_API_KEY"]
RANGES = ["203.0.113.0/24", "198.51.100.0/25"]
PREVIOUS_REPORT = "previous_report.csv"
CURRENT_REPORT = "attack_surface_report.csv"
api = shodan.Shodan(API_KEY)
current_rows = []
for cidr in RANGES:
results = api.search(f"net:{cidr}")
for match in results["matches"]:
vulns = match.get("vulns", {})
current_rows.append({
"ip": match["ip_str"],
"port": str(match["port"]),
"product": match.get("product", ""),
"vulns": ";".join(vulns.keys()) if vulns else "",
})
with open(CURRENT_REPORT, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["ip", "port", "product", "vulns"])
writer.writeheader()
writer.writerows(current_rows)
previous_keys = set()
if os.path.exists(PREVIOUS_REPORT):
with open(PREVIOUS_REPORT) as f:
for row in csv.DictReader(f):
previous_keys.add((row["ip"], row["port"]))
new_findings = [r for r in current_rows if (r["ip"], r["port"]) not in previous_keys]
if new_findings:
print(f"{len(new_findings)} new exposed services found this week:")
targets = list({r["ip"] for r in new_findings})
with open("new_targets.txt", "w") as f:
f.write("n".join(targets))
subprocess.run(["nmap", "-sV", "-Pn", "-iL", "new_targets.txt", "-oN", "verification.txt"])
for r in new_findings:
print(f" {r['ip']}:{r['port']} ({r['product']}) vulns={r['vulns']}")
else:
print("No new exposure detected this week.")
os.replace(CURRENT_REPORT, PREVIOUS_REPORT)
Sample output from a run against a small test range looks like this:
2 new exposed services found this week:
203.0.113.45:27017 (MongoDB) vulns=
198.51.100.12:502 (Modbus) vulns=CVE-2022-1234
Starting Nmap 7.95 ( https://nmap.org )
Nmap scan report for 203.0.113.45
PORT STATE SERVICE
27017/tcp open mongodb
Nmap scan report for 198.51.100.12
PORT STATE SERVICE
502/tcp open modbus
Wire this into cron with a weekly schedule (`0 6 * * 1` for Monday mornings), point the environment variable at your API key via a secrets manager rather than a hardcoded string, and you have a durable, low-maintenance attack surface monitoring process that costs a fraction of a commercial ASM platform’s license fee.
Frequently Asked Questions
Is Shodan legal to use?
Searching Shodan’s existing index is generally lawful in most jurisdictions because you are viewing data Shodan already collected from services that responded to standard connection attempts on the public internet. Acting on what you find, such as logging into an exposed system, is a separate matter and can violate computer-misuse laws even if the credentials work.
Do I need a paid plan to get useful results?
The free tier is enough to learn the interface, but real filters and meaningful query volume require at least the $49 one-time Membership, and ongoing scripted work is more practical on the $69/month Freelancer tier.
How current is Shodan’s data?
Shodan scans continuously but not instantaneously; any given host’s banner could be hours or weeks old depending on scan cadence for that range. Always verify a finding with a live scan before treating it as current.
What’s the difference between Shodan and a vulnerability scanner?
Shodan indexes what services are exposed and matches banners against known CVEs, but it does not actively exploit anything to confirm a vulnerability. A scanner like nuclei runs live proof-of-concept checks against a target, which is a necessary follow-up step rather than a replacement for Shodan’s discovery role.
Can Shodan monitor my cloud infrastructure automatically?
Yes, through Shodan Monitor, which tracks declared IP ranges continuously and alerts on new ports, banner changes, or newly matched CVEs, with monitored-IP quotas scaling by plan tier.
Should I use Shodan or Censys?
They overlap but are not identical: Shodan leans toward device banners, ports, and ICS/IoT coverage, while Censys leans toward certificate and TLS-focused host data. Many security programs run both rather than choosing one.
What happens if I find someone else’s exposed database?
Do not download, modify, or publicize the data. Route the finding through a responsible disclosure channel, such as the organization’s security.txt contact or a coordinated disclosure platform, and document when and how you found it.
Can Shodan replace an internal vulnerability management program?
No. Shodan gives you the external, attacker’s-eye view of your perimeter, which is a valuable input but not a substitute for internal scanning, patch management, and asset inventory processes that cover systems Shodan cannot see, such as internal-only services behind a VPN.