Do you want to see where an IP is located? Which ports/ services it has available? The Shodan API gives you the ability to quickly lookup information for an IP.
The shodan Python package is required for this tutorial and a valid API key, which is available for free with every Shodan account. You can install it using easy_install or pip:
$ sudo pip install shodan
You can get your Shodan API key from your account page at:
Looking up IPs is free and doesn't require a paid account, though you're rate limited to 1 lookup per second.
To lookup information about an IP we will use the Shodan.host() method. Getting started with the basics is straight-forward:
import shodan
api = shodan.Shodan('YOUR API KEY')
info = api.host('8.8.8.8')
The above code requests information about Google's DNS resolver 8.8.8.8 and stores it in the info variable. Here is a closer look at the data that the info object now holds:
{
"data": [
{
"asn": "AS15169",
"hash": -553166942,
"ip": 134744072,
"isp": "Google",
"transport": "udp",
"data": "\nRecursion: enabled",
"port": 53,
"hostnames": [
"google-public-dns-a.google.com"
],
"location": {
"city": null,
"region_code": null,
"area_code": null,
"longitude": -97.822,
"country_code3": "USA",
"latitude": 37.751000000000005,
"postal_code": null,
"dma_code": null,
"country_code": "US",
"country_name": "United States"
},
"timestamp": "2018-03-16T03:06:34.553526",
"domains": [
"google.com"
],
"org": "Google",
"os": null,
"_shodan": {
"crawler": "6ff540e4d43ec69d8de2a7b60e1de2d9ddb406dc",
"options": {},
"module": "dns-udp",
"id": null
},
"opts": {},
"ip_str": "8.8.8.8"
}
],
"city": null,
"region_code": null,
"tags": [],
"ip": 134744072,
"isp": "Google",
"area_code": null,
"dma_code": null,
"last_update": "2018-03-16T03:06:34.553526",
"country_code3": "USA",
"latitude": 37.751000000000005,
"hostnames": [
"google-public-dns-a.google.com"
],
"postal_code": null,
"longitude": -97.822,
"country_code": "US",
"org": "Google",
"country_name": "United States",
"ip_str": "8.8.8.8",
"os": null,
"asn": "AS15169",
"ports": [
53
]
}
The result from api.host() contains information about the services it runs, where it's located, the hosting provider and more. There are a few top-level properties of note:
There are a few common reasons to look at a history of an IP:
We can get a full history of an IP address by providing an optional history=True parameter:
import shodan
api = shodan.Shodan('YOUR API KEY')
info = api.host('8.8.8.8', history=True)
The resulting info object will have the same structure as before but the top-level data property now contains a list of all the banners that were ever seen for that IP.
The Corporate API plan gives you the ability to lookup 100 IPs per request. If you're building a data processing pipeline that wants to do a lot of IP enrichment then doing bulk IP lookups is the way to go. And using them is nearly the same as doing individual IP lookups:
import shodan
api = shodan.Shodan('YOUR CORPORATE API KEY')
hosts = api.host([
'8.8.8.8',
'8.8.4.4',
])
for info in hosts:
# Each record in the "hosts" list is what an individual IP lookup returns
print(info['ip_str'])
# The above is equivalent to doing
info = api.host('8.8.8.8')
# ...
info = api.host('8.8.4.4')
Instead of giving the Shodan.host() method an IP address we can also give it a list of IPs. The result of a bulk IP lookup is a list of objects where each object contains the same information you'd see when doing an individual IP lookup.