Skip to content

Instantly share code, notes, and snippets.

@helgibbons
Last active December 2, 2025 13:11
Show Gist options
  • Select an option

  • Save helgibbons/7c6918b4389c31723eec8e9ed9481036 to your computer and use it in GitHub Desktop.

Select an option

Save helgibbons/7c6918b4389c31723eec8e9ed9481036 to your computer and use it in GitHub Desktop.
Attempt to work around Comic Vine's new Cloudflare shenanigans
"""
Python script to fetch a randomised comic cover from the Comic Vine API and show it on an Inky Impression display.
You will need to sign up for an API key at https://comicvine.gamespot.com/api/ to use this script.
Change the search query to the comic series you want to display!
"""
import json
import random
import time
from io import BytesIO
from urllib import parse, request
from PIL import Image
from inky.auto import auto
# Comic Vine API details
API_KEY = "API_KEY_GOES_HERE" # Replace with your Comic Vine API key
BASE_URL = "https://comicvine.gamespot.com/api/"
HEADERS = {
"authority": "www.google.com",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "en-US,en;q=0.9",
"cache-control": "max-age=0",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
# List of comic series to display, separated by commas. You can add more series to this list, or change the existing ones.
SEARCH_QUERIES = ["Weird Science"]
# Set to True to pick a random volume from the query results (this is helpful if the series is split into multiple volumes):
RANDOM_VOLUME = True
# Inky Impression display setup
inky_display = auto()
def find_volume_id(api_key, query):
# Our first API call finds a list of volumes that match the search query, and then picks one
params = {
"query": query,
"resources": "volume",
"limit": 5,
"api_key": api_key,
"format": "json"
}
url = f"{BASE_URL}search/?{parse.urlencode(params)}"
req = request.Request(url, headers=HEADERS)
try:
with request.urlopen(req) as resp:
data = resp.read()
parsed = json.loads(data.decode("utf-8"))
results = parsed.get("results", [])
except Exception as e:
raise RuntimeError(f"Failed to search for volumes: {e}")
if results:
for idx, volume in enumerate(results, 1):
print(f"{idx}: {volume['name']} (ID: {volume['id']}, Start Year: {volume.get('start_year', 'N/A')})")
if RANDOM_VOLUME:
chosen = random.choice(results)
print(f"Randomly selected: {chosen['name']} (ID: {chosen['id']})")
else:
chosen = results[0]
print("Picked first result!")
return chosen["id"]
else:
raise ValueError("No volumes found for the given query.")
def fetch_random_comic_image(api_key, series_id):
"""Fetch a random comic cover image from the given series."""
params = {
"filter": f"volume:{series_id}",
"limit": 100,
"api_key": api_key,
"format": "json"
}
url = f"{BASE_URL}issues/?{parse.urlencode(params)}"
req = request.Request(url, headers=HEADERS)
try:
with request.urlopen(req) as resp:
data = resp.read()
parsed = json.loads(data.decode("utf-8"))
results = parsed.get("results", [])
except Exception as e:
raise RuntimeError(f"Failed to fetch comic issues: {e}")
if results:
issue = random.choice(results)
print(f"Random issue selected: ID: {issue['id']}")
print(f"Find out more: {issue['site_detail_url']}")
return issue["image"]["original_url"]
else:
raise ValueError("No comic issues found for the specified series.")
def display_image_on_inky(image_url):
"""Download and display image on Inky Impression."""
try:
# Download the image
req = request.Request(image_url, headers=HEADERS)
with request.urlopen(req) as resp:
image_bytes = resp.read()
# Open and process the image
image = Image.open(BytesIO(image_bytes))
# Rotate if taller than wide
if image.height > image.width:
image = image.rotate(90, expand=True)
# Resize and display
image = image.resize(inky_display.resolution)
inky_display.set_image(image)
print("Updating Inky Impression!")
inky_display.show()
except Exception as e:
raise RuntimeError(f"Failed to display image: {e}")
try:
# Pick a random search term from the list
search_query = random.choice(SEARCH_QUERIES)
print("Searching for volumes...")
volume_id = find_volume_id(API_KEY, search_query)
# Wait 2 seconds between API calls
print("Waiting before fetching issues...")
time.sleep(2)
comic_image_url = fetch_random_comic_image(API_KEY, volume_id)
# Wait 2 seconds before downloading image
print("Waiting before downloading image...")
time.sleep(2)
display_image_on_inky(comic_image_url)
except Exception as e:
print(f"Error: {e}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment