Shodan GeoPing – Quick‑Start Guide
Runs a Shodan GeoPing query against a domain, collects RTT and packet‑loss data from many global locations, and prints a concise, tabulated report.
- Python 3.8+
pip(oruv)
pip install requests tabulate
# Create a virtual environment (optional but recommended)
uv venv shodangeoping
source shodangeoping/bin/activate
# Install dependencies
uv pip install requests tabulate
# Save the script below as shodangeoping.py
# Make it executable
chmod +x shodangeoping.py
# Run it
./shodangeoping.py -d example.com./shodangeoping.py -d <domain>-d,--domain– Target domain (e.g.,example.com).-h,--help– Show help.
Shodan GeoPing Performance Tester
============================================================
Test started at: 2026-03-20 09:43:57
============================================================
[*] Testing performance for domain: example.com
[*] Querying Shodan GeoPing API...
=== GLOBAL PERFORMANCE OVERVIEW ===
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
| IP | Location | Coordinates | Status | Min RTT (ms) | Avg RTT (ms) | Max RTT (ms) | Packets Sent | Packets Received | Packet Loss (%) |
+===============+=======================+==================+==========+================+================+================+================+====================+===================+
| 104.18.27.120 | Clifton, US | 40.8584,-74.1638 | Alive | 1.693 | 2.311 | 3.525 | 3 | 3 | 0.0% |
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
| 104.18.27.120 | London, GB | 51.5085,-0.1257 | Alive | 2.463 | 2.689 | 2.942 | 3 | 3 | 0.0% |
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
| 104.18.27.120 | Amsterdam, NL | 52.3740,4.8897 | Alive | 1.06 | 1.353 | 1.909 | 3 | 3 | 0.0% |
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
| 104.18.26.120 | Frankfurt am Main, DE | 50.1155,8.6842 | Alive | 1.045 | 1.39 | 2.019 | 3 | 3 | 0.0% |
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
| 104.18.26.120 | Singapore, SG | 1.3215,103.6957 | Alive | 1.2 | 1.5 | 2.011 | 3 | 3 | 0.0% |
+---------------+-----------------------+------------------+----------+----------------+----------------+----------------+----------------+--------------------+-------------------+
=== PERFORMANCE ANALYSIS ===
Target Domain: example.com
Total Locations Tested: 5
Average RTT Across All Locations: 1.849 ms
Highest RTT: 3.525 ms
Lowest RTT: 1.045 ms
Average Packet Loss: 0.0%
[+] Test completed successfully
[+] Test ended at: 2026-03-20 09:44:00
============================================================
#!/usr/bin/env python3
import sys
import argparse
import requests
from datetime import datetime
from tabulate import tabulate
BANNER = r"""
██████ ██░ ██ ▒█████ ▓█████▄ ▄▄▄ ███▄ █ ▄████ ▓█████ ▒█████ ██▓███ ██▓ ███▄ █ ▄████
▒██ ▒ ▒▓██░ ██ ▒██▒ ██▒▒██▀ ██▌▒████▄ ██ ▀█ █ ▒ ██▒ ▀█▒ ▓█ ▀▒██▒ ██▒ ▓██░ ██ ▒▓██▒ ██ ▀█ █ ██▒ ▀█
░ ▓██▄ ░▒██▀▀██ ▒██░ ██▒░██ █▌▒██ ▀█▄ ▓██ ▀█ ██▒ ░▒██░▄▄▄░ ▒███ ▒██░ ██▒ ▓██░ ██▓▒▒▒██▒▓██ ▀█ ██▒▒██░▄▄▄
▒ ██▒ ░▓█ ░██ ▒██ ██░░▓█▄ ▌░██▄▄▄▄██▓██▒ ▐▌██▒ ░░▓█ ██▓ ▒▓█ ▄▒██ ██░ ▒██▄█▓▒ ▒░░██░▓██▒ ▐▌██▒░▓█ ██
▒██████▒▒ ░▓█▒░██▓░ ████▓▒░░▒████▓ ▒▓█ ▓██▒▓██▒ ▐▌██▒ ░ ▓█ █░▒▓█ █▓████▓░ ░█████▒ ████▒ █████▒ ░███
"""
def print_banner():
print("=" * 60)
print("Shodan GeoPing Performance Tester")
print(f"Test started at: {datetime.now():%Y-%m-%d %H:%M:%S}")
print("=" * 60)
def get_performance_data(domain: str):
url = f"https://api.shodan.io/shodan/geo?host={domain}"
resp = requests.get(url, timeout=10)
resp.raise_for_status()
return resp.json()
def process_data(raw):
return [
{
"ip": item["ip"],
"location": f'{item["location"]["city"]}, {item["location"]["country"]}',
"coordinates": f'{item["location"]["latitude"]},{item["location"]["longitude"]}',
"status": "Alive" if item.get("status", "").lower() == "alive" else "Lost",
"min_rtt": f'{item["stats"]["rtt_min"]:.3f}',
"avg_rtt": f'{item["stats"]["rtt_avg"]:.3f}',
"max_rtt": f'{item["stats"]["rtt_max"]:.3f}',
"packets_sent": item["stats"]["sent"],
"packets_recv": item["stats"]["recv"],
"packet_loss": f'{item["stats"]["packet_loss"]:.1f}%',
}
for item in raw
]
def display_results(data, domain):
table = [
[
d["ip"],
d["location"],
d["coordinates"],
d["status"],
d["min_rtt"],
d["avg_rtt"],
d["max_rtt"],
d["packets_sent"],
d["packets_recv"],
d["packet_loss"],
]
for d in data
]
print("\n=== GLOBAL PERFORMANCE OVERVIEW ===")
print(tabulate(table, headers=[
"IP", "Location", "Coordinates", "Status",
"Min RTT (ms)", "Avg RTT (ms)", "Max RTT (ms)",
"Packets Sent", "Packets Received", "Packet Loss (%)",
], tablefmt="grid"))
avg_rtt = sum(float(d["avg_rtt"]) for d in data) / len(data)
max_rtt = max(float(d["max_rtt"]) for d in data)
min_rtt = min(float(d["min_rtt"]) for d in data)
avg_loss = sum(float(d["packet_loss"].rstrip("%")) for d in data) / len(data)
print("\n=== PERFORMANCE ANALYSIS ===")
print(f"\nTarget Domain: {domain}")
print(f"Total Locations Tested: {len(data)}")
print(f"Average RTT Across All Locations: {avg_rtt:.3f} ms")
print(f"Highest RTT: {max_rtt:.3f} ms")
print(f"Lowest RTT: {min_rtt:.3f} ms")
print(f"Average Packet Loss: {avg_loss:.1f}%")
def main():
parser = argparse.ArgumentParser(
description="Run a Shodan GeoPing query and display RTT/packet‑loss stats.",
formatter_class=argparse.RawTextHelpFormatter,
)
parser.add_argument('-d', '--domain', required=True, help='Target domain (e.g., example.com)')
args = parser.parse_args()
print_banner()
print(f"\n[*] Testing performance for domain: {args.domain}")
print("\n[*] Querying Shodan GeoPing API...")
data = get_performance_data(args.domain)
processed = process_data(data)
display_results(processed, args.domain)
print("\n[+] Test completed successfully")
print(f"[+] Test ended at: {datetime.now():%Y-%m-%d %H:%M:%S}")
print("=" * 60)
if __name__ == "__main__":
main()Note: The script assumes the public Shodan GeoPing endpoint is reachable. If you encounter rate limits or API key requirements, refer to Shodan’s documentation for the correct query URL and authentication.