ShadowScan is a small CLI that queries the Shodan Host API for one or more hosts and prints Nmap-style output.
Important
Use ShadowScan only on hosts you are authorized to assess.
ShadowScan is a passive lookup tool (it does not probe/scan targets). Output reflects what Shodan has indexed.
- 🕵️ Passive Shodan Host API lookup (no scanning)
- 🎯 Multi-target input: positional targets,
--input, and--cidr - 🧰 Filters:
--ports,--proto,--service,--grep - 🧾 Output:
--format nmap|summary|json|ndjson|grep|xmlplus-oN/-oG/-oX - 💾 Caching:
--cache-dir,--cache-ttl,--no-cache - 🧯 Safety rails:
--authorized-scope,--dry-run,--max-targets
# API key (current session)
$env:SHODAN_API_KEY = "YOUR_KEY"
# Single target
python .\shadowscan.py 8.8.8.8
# File input
python .\shadowscan.py --input targets.txt
# CIDR with allowlist
python .\shadowscan.py --cidr 10.0.0.0/24 --authorized-scope scope.txtRequirements:
- Python 3.9+
- A Shodan API key in
SHODAN_API_KEY
Install options:
# Install the latest release (recommended)
pipx install "git+https://github.com/vgg-dev/shadowscan.git@v0.1.0"
# Or install from main
pipx install "git+https://github.com/vgg-dev/shadowscan.git@main"Run as:
shadowscan --help
shadowscan 8.8.8.8Optional (virtual environment):
python -m venv .venv
.\.venv\Scripts\Activate.ps1Single target (default Nmap-style):
python .\shadowscan.py 8.8.8.8
python .\shadowscan.py example.com --resolveMultiple targets:
python .\shadowscan.py --input targets.txt
python .\shadowscan.py --cidr 10.0.0.0/24
python .\shadowscan.py 1.1.1.1 8.8.8.8Filters + banners:
python .\shadowscan.py 8.8.8.8 --ports 80,443 --show-banners
python .\shadowscan.py 8.8.8.8 --grep "nginx" --show-bannersRaw JSON / pipelines:
python .\shadowscan.py 8.8.8.8 --format json
python .\shadowscan.py --input targets.txt --format ndjsonWrite Nmap-ish output files:
python .\shadowscan.py --input targets.txt -oN out.txt -oG out.grep -oX out.xmlTo help avoid accidental lookups outside an authorized scope:
--authorized-scope scope.txtblocks targets not in the allowlist (CIDRs/IPs;#comments supported)--dry-runprints the resolved targets and exits (no API calls)--max-targetslimits--cidrexpansion unless--allow-largeis set--forceoverrides allowlist blocking (use with care)
Primary stdout formats:
python .\shadowscan.py 8.8.8.8 --format nmap
python .\shadowscan.py 8.8.8.8 --format summary
python .\shadowscan.py 8.8.8.8 --format json
python .\shadowscan.py --input targets.txt --format ndjson
python .\shadowscan.py 8.8.8.8 --format grep
python .\shadowscan.py 8.8.8.8 --format xmlBy default, responses are cached to .shadowscan-cache/ for 1 hour.
python .\shadowscan.py 8.8.8.8 --cache-ttl 0 # disable cache reads (always refresh)
python .\shadowscan.py 8.8.8.8 --no-cache # disable cache reads/writes
python .\shadowscan.py 8.8.8.8 --cache-ttl 86400 # 24h TTL- 401/403: verify
SHODAN_API_KEYis set and has access to the Host API. - 429 (rate limit): use
--retries/--backoffand reduce target count. - Name resolution errors: use an IP directly, or check DNS;
--resolveis only for hostnames.
- Do not commit API keys.
- Raw JSON output can contain service banners; treat it as potentially sensitive.
- CI runs on every push/PR via GitHub Actions.
- Releases: push a tag like
v0.1.0to builddist/*and create a GitHub Release. - Optional PyPI publish: set repo secret
PYPI_API_TOKENto enable publishing.
Tag example:
git tag v0.1.0
git push origin v0.1.0MIT — see LICENSE.