stock-images

Installation
SKILL.md

Stock Images from Unsplash

Search Unsplash for images, download them, and optionally add text overlay.

Prerequisites

  • Unsplash API key in UNSPLASH_CLIENT_ID environment variable (register at unsplash.com/developers)
  • Python 3 with requests and Pillow (for text overlay)

Usage

Search and Download

import os, requests, random

def search_unsplash(query, orientation=None, count=30):
    """Search Unsplash and return photo results."""
    params = {
        "query": query,
        "per_page": count,
        "client_id": os.environ["UNSPLASH_CLIENT_ID"],
    }
    if orientation:
        params["orientation"] = orientation  # landscape, portrait, squarish
    resp = requests.get("https://api.unsplash.com/search/photos", params=params)
    resp.raise_for_status()
    return resp.json()["results"]

def download_photo(photo, output_path):
    """Download a photo's regular-size image."""
    url = photo["urls"]["regular"]
    resp = requests.get(url)
    resp.raise_for_status()
    with open(output_path, "wb") as f:
        f.write(resp.content)
    # Trigger download tracking (required by Unsplash API terms)
    requests.get(photo["links"]["download_location"],
                 params={"client_id": os.environ["UNSPLASH_CLIENT_ID"]})
    print(f"Photo by {photo['user']['name']} on Unsplash")

# Example: search and download a random matching photo
results = search_unsplash("nature landscape", orientation="landscape")
photo = random.choice(results)
download_photo(photo, "./image.jpg")

With Text Overlay

from PIL import Image, ImageDraw, ImageFont

def add_text_overlay(image_path, title, subtitle=None, output_path=None):
    """Add title/subtitle overlay to an image."""
    img = Image.open(image_path)
    draw = ImageDraw.Draw(img)
    width, height = img.size

    # Semi-transparent overlay at bottom
    overlay_height = height // 4
    overlay = Image.new("RGBA", (width, overlay_height), (0, 0, 0, 128))
    img.paste(overlay, (0, height - overlay_height), overlay)

    # Title text
    try:
        font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 48)
        small_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 28)
    except OSError:
        font = ImageFont.load_default()
        small_font = font

    title_y = height - overlay_height + 20
    draw.text((40, title_y), title, fill="white", font=font)

    if subtitle:
        draw.text((40, title_y + 60), subtitle, fill=(200, 200, 200), font=small_font)

    out = output_path or image_path
    img.save(out)

add_text_overlay("./image.jpg", "My Blog Post Title", "A short description")

CLI Options to Support

When building a script, support these options:

Option Description
--query Search query string (required)
--output Output file path (required unless listing)
--orientation Filter: landscape, portrait, or squarish
--color Color filter (e.g., blue, green, black_and_white)
--pick Selection mode: random (default) or first
--title Title text to overlay on the image
--subtitle Subtitle text (only used with --title)
--list List results without downloading
--count Number of results to fetch, max 30 (default: 30)

Important Notes

  • Attribution required: Unsplash requires crediting the photographer. Always include Photo by {name} on Unsplash in your output.
  • Download tracking: Trigger the download endpoint as required by Unsplash API terms.
  • Rate limits: 50 requests/hour for demo apps, 5000/hour for production apps.
  • Image sizes: raw (original), full (high-res), regular (1080px wide), small (400px), thumb (200px).
Weekly Installs
29
GitHub Stars
406
First Seen
Mar 25, 2026