Skip to content

Instantly share code, notes, and snippets.

Created November 25, 2017 06:18
Show Gist options
  • Save achillean/7190d53841865a8c9978f59863669857 to your computer and use it in GitHub Desktop.
Save achillean/7190d53841865a8c9978f59863669857 to your computer and use it in GitHub Desktop.
Timelapse GIF Creator using the Shodan API
#!/usr/bin/env python
# Dependencies:
# - arrow
# - shodan
# Installation:
# sudo easy_install arrow shodan
# sudo apt-get install imagemagick
# Usage:
# 1. Download a json.gz file using the website or the Shodan command-line tool (
# For example:
# shodan download --limit=100 screenshots.json.gz has_screenshot:true
# 2. Run the tool on the file:
# python screenshots.json.gz
import arrow
import os
import shodan
import shodan.helpers as helpers
import sys
# Settings
API_KEY = ''
# The user has to provide at least 1 Shodan data file
if len(sys.argv) < 2:
print('Usage: {} <shodan-data.json.gz> ...'.format(sys.argv[0]))
# GIFs are stored in the local "data" directory
# Setup the Shodan API object
api = shodan.Shodan(API_KEY)
# Loop over all of the Shodan data files the user provided
for banner in helpers.iterate_files(sys.argv[1:]):
# See whether the current banner has a screenshot, if it does then lets lookup
# more information about this IP
has_screenshot = helpers.get_screenshot(banner)
if has_screenshot:
ip = helpers.get_ip(banner)
print('Looking up {}'.format(ip))
host =, history=True)
# Store all the historical screenshots for this IP
screenshots = []
for tmp_banner in host['data']:
# Try to extract the image from the banner data
screenshot = helpers.get_screenshot(tmp_banner)
if screenshot:
# Sort the images by the time they were collected so the GIF will loop
# based on the local time regardless of which day the banner was taken.
timestamp = arrow.get(banner['timestamp']).time()
sort_key = timestamp.hour
# Add the screenshot to the list of screenshots which we'll use to create the timelapse
# Extract the screenshots and turn them into a GIF if we've got more than a few images
if len(screenshots) >= 3:
# screenshots is a list where each item is a tuple of:
# (sort key, screenshot in base64 encoding)
# Lets sort that list based on the sort key and then use Python's enumerate
# to generate sequential numbers for the temporary image filenames
for (i, screenshot) in enumerate(sorted(screenshots, key=lambda x: x[0], reverse=True)):
# Create a temporary image file
# TODO: don't assume that all images are "jpg", use the mimetype instead
open('/tmp/gif-image-{}.jpg'.format(i), 'w').write(screenshot[1].decode('base64'))
# Create the actual GIF using the ImageMagick "convert" command
# The resulting GIFs are stored in the local data/ directory
os.system('convert -layers OptimizePlus -delay 5x10 /tmp/gif-image-*.jpg -loop 0 +dither -colors 256 -depth 8 data/{}.gif'.format(ip))
# Clean up the temporary files
os.system('rm -f /tmp/gif-image-*.jpg')
# Show a progress indicator
print('GIF created for {}'.format(ip))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment