A comprehensive guide for AI agents to search, retrieve, and curate images from various online sources. Covers free stock photos, academic figures, news images, product photos, scientific illustrations, and more.
Before fetching images, check which tools/APIs are available in the current environment:
https://api.unsplash.comAuthorization: Bearer <ACCESS_KEY>bash
# Search photos
curl -H "Authorization: Bearer $UNSPLASH_ACCESS_KEY" \
"https://api.unsplash.com/search/photos?query=renewable+energy&per_page=10&orientation=landscape"
# Get a random photo
curl -H "Authorization: Bearer $UNSPLASH_ACCESS_KEY" \
"https://api.unsplash.com/photos/random?query=technology&orientation=squarish"
# Download tracked photo (respects photographer attribution)
curl -H "Authorization: Bearer $UNSPLASH_ACCESS_KEY" \
-L "https://api.unsplash.com/photos/<PHOTO_ID>/download"
Response fields: results[].urls.raw, results[].urls.full, results[].urls.regular, results[].urls.small, results[].user.name, results[].links.html
https://api.pexels.com/v1Authorization: <API_KEY>bash
# Search photos
curl -H "Authorization: $PEXELS_API_KEY" \
"https://api.pexels.com/v1/search?query=nature&per_page=10&orientation=landscape"
# Curated photos
curl -H "Authorization: $PEXELS_API_KEY" \
"https://api.pexels.com/v1/curated?per_page=15"
# Get photo by ID
curl -H "Authorization: $PEXELS_API_KEY" \
"https://api.pexels.com/v1/photos/<PHOTO_ID>"
https://pixabay.com/apikey=<API_KEY>bash
# Search images
curl "https://pixabay.com/api/?key=$PIXABAY_API_KEY&q=mountain+landscape&image_type=photo&per_page=10&safesearch=true"
# Search vectors/illustrations
curl "https://pixabay.com/api/?key=$PIXABAY_API_KEY&q=robot&image_type=vector&per_page=10"
# Search videos
curl "https://pixabay.com/api/videos/?key=$PIXABAY_API_KEY&q=ocean&per_page=5"
Categories: backgrounds, fashion, nature, science, education, feelings, health, people, religion, places, animals, industry, computer, food, sports, transportation, travel, buildings, business, music
https://api.flickr.com/services/restlicense=1,2,4,5,9 for CC-compatiblebash
# Search photos (CC license only)
curl "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=$FLICKR_API_KEY&text=sunset&license=1,2,4,5,9&per_page=10&format=json&nojsoncallback=1"
# Get photo URL: https://farm{farm}.staticflickr.com/{server}/{id}_{secret}.jpg
https://www.googleapis.com/customsearch/v1bash
# Search images
curl "https://www.googleapis.com/customsearch/v1?key=$GOOGLE_API_KEY&cx=$GOOGLE_CX&searchType=image&q=AI+conference+2024&num=10&imgSize=large"
https://api.bing.microsoft.com/v7.0/images/searchOcp-Apim-Subscription-Key: <KEY>bash
curl -H "Ocp-Apim-Subscription-Key: $BING_API_KEY" \
"https://api.bing.microsoft.com/v7.0/images/search?q=cute+cats&count=10&imageType=Photo&size=Large"
bash
# Extract content + images from a URL
node ~/.openclaw/workspace/skills/tavily-search/scripts/extract.mjs "https://example.com/article" --include-images true
bash
npx skills add openags/paper-search-mcp
# or with uv:
uv tool install paper-search-mcp
bash
# Search papers
curl "https://api.semanticscholar.org/graph/v1/paper/search?query=protein+folding&limit=10&fields=title,url,openAccessPdf"
bash
# Search papers with figure references
curl "https://api.semanticscholar.org/graph/v1/paper/search?query=transformer+architecture&limit=5&fields=title,url,openAccessPdf,figures"
bash
# Search papers
curl "http://export.arxiv.org/api/query?search_query=all:electron+microscopy&start=0&max_results=5"
bash
# Search PMC for figures
curl "https://www.ncbi.nlm.nih.gov/pmc/utils/oa/oa.fcgi?id=PMC1234567" # get full text XML with figures
For combining multiple images into a single figure with (a), (b), (c) labels - standard in academic papers.
python
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
def create_figure_grid(image_paths, labels=None, cols=2, label_font_size=20,
label_position='top-left', padding=20, label_color='white',
bg_color='white', dpi=300, output_path='figure.png'):
"""
Combine multiple images into a single academic figure with (a)(b)(c) labels.
Args:
image_paths: List of image file paths
labels: List of label strings (default: a, b, c, ...)
cols: Number of columns
label_font_size: Font size for labels
label_position: 'top-left', 'top-right', 'bottom-left', 'bottom-right'
padding: Space between images in pixels
label_color: Color of labels ('white' or 'black')
bg_color: Background color
dpi: Output DPI
output_path: Output file path
"""
if labels is None:
labels = [chr(ord('a') + i) for i in range(len(image_paths))]
rows = (len(image_paths) + cols - 1) // cols
images = [Image.open(p).convert('RGB') for p in image_paths]
# Find max dimensions
max_w = max(img.width for img in images)
max_h = max(img.height for img in images)
# Create canvas
total_w = cols * max_w + (cols + 1) * padding
total_h = rows * max_h + (rows + 1) * padding
canvas = Image.new('RGB', (total_w, total_h), bg_color)
draw = ImageDraw.Draw(canvas)
# Try to load a font
try:
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", label_font_size)
except:
font = ImageFont.load_default()
for idx, (img, label) in enumerate(zip(images, labels)):
row, col = idx // cols, idx % cols
x = padding + col * (max_w + padding)
y = padding + row * (max_h + padding)
canvas.paste(img, (x, y))
# Draw label
label_text = f"({label})"
bbox = draw.textbbox((0, 0), label_text, font=font)
lw, lh = bbox[2] - bbox[0], bbox[3] - bbox[1]
margin = 10
if label_position == 'top-left':
lx, ly = x + margin, y + margin
elif label_position == 'top-right':
lx, ly = x + max_w - lw - margin, y + margin
elif label_position == 'bottom-left':
lx, ly = x + margin, y + max_h - lh - margin
else:
lx, ly = x + max_w - lw - margin, y + max_h - lh - margin
# Draw background rectangle for readability
draw.rectangle([lx - 4, ly - 2, lx + lw + 4, ly + lh + 2], fill=label_color, outline=label_color)
text_color = 'black' if label_color == 'white' else 'white'
draw.text((lx, ly), label_text, fill=text_color, font=font)
canvas.save(output_path, dpi=(dpi, dpi))
print(f"Figure saved to {output_path}")
return canvas
# Usage
create_figure_grid(
image_paths=['fig1.png', 'fig2.png', 'fig3.png', 'fig4.png'],
labels=['a', 'b', 'c', 'd'],
cols=2,
output_path='combined_figure.png'
)
python
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def subplot_figure(image_paths, labels=None, cols=2, figsize=(12, 10),
label_size=16, label_weight='bold', output_path='figure.pdf'):
"""Create academic figure using matplotlib subplots with (a)(b)(c) labels."""
if labels is None:
labels = [chr(ord('a') + i) for i in range(len(image_paths))]
rows = (len(image_paths) + cols - 1) // cols
fig, axes = plt.subplots(rows, cols, figsize=figsize)
axes = axes.flatten() if hasattr(axes, 'flatten') else [axes]
for ax, path, label in zip(axes, image_paths, labels):
img = mpimg.imread(path)
ax.imshow(img)
ax.set_title(f'({label})', fontsize=label_size, fontweight=label_weight, loc='left')
ax.axis('off')
# Hide empty subplots
for ax in axes[len(image_paths):]:
ax.axis('off')
plt.tight_layout()
fig.savefig(output_path, dpi=300, bbox_inches='tight')
print(f"Saved to {output_path}")
# Usage
subplot_figure(['a.png', 'b.png', 'c.png'], cols=3, output_path='fig1.pdf')
bash
# Simple 2x2 grid
montage img1.png img2.png img3.png img4.png -tile 2x2 -geometry +5+5 output.png
# With labels (requires additional steps)
# Better to use the Python script above for labeled figures
bash
node ~/.openclaw/workspace/skills/tavily-search/scripts/search.mjs "AI breakthrough 2024" --topic news --days 7
https://newsapi.org/v2apiKey query param or X-Api-Key headerbash
# Search news with images
curl "https://newsapi.org/v2/everything?q=AI+research&apiKey=$NEWSAPI_KEY&pageSize=10"
# Articles include urlToImage field
https://gnews.io/api/v4token query param or apikey headerbash
curl "https://gnews.io/api/v4/search?q=climate+change&token=$GNEWS_API_KEY&lang=en&max=10"
https://webservices.amazon.com/paapi5bash
# Search products with images (via PA-API)
curl -X POST "https://webservices.amazon.com/paapi5/searchitems" \
-H "Content-Type: application/json" \
-d '{"Keywords":"wireless headphones","SearchIndex":"Electronics","ItemCount":10}'
amazon scraper, taobao scraper, ebay scraperhttps://oauth.reddit.com/search.json?q=<query>&type=linkhttps://graph.instagram.combash
# Search images via MediaWiki API
curl "https://commons.wikimedia.org/w/api.php?action=query&generator=search&gsrnamespace=6&gsrsearch=cat+breeds&gsrlimit=10&prop=imageinfo&iiprop=url|extmetadata&format=json"
# Get random featured picture
curl "https://commons.wikimedia.org/w/api.php?action=query&list=random&rnnamespace=6&rnlimit=5&prop=imageinfo&iiprop=url&format=json"
Use the image_generate tool directly - supports DALL-E, Gemini, and other providers.
mcp-image (Nano Banana): AI image generation via Gemini
npx mcp-image with GEMINI_API_KEYfal.ai MCP: Multi-provider image generation
Flux MCP: Flux model image generation
Use CaseBest SourcesNotesAcademic papersSemantic Scholar, arXiv, PubMedCheck open access for figuresBlog postsUnsplash, Pexels, PixabayFree commercial usePresentationsUnsplash, Wikimedia CommonsHigh resolution preferredSocial mediaUnsplash, Pexels, PixabaySquare/vertical formatsProduct imagesPlatform APIs, scraperCheck ToSNews articlesNewsAPI, Tavily news, Google NewsurlToImage fieldScientific figuresFigureLabs, BioRender, matplotlibGenerate, don't searchData visualizationsReddit r/dataisbeautiful, ObservableCheck licensingIcons/illustrationsPixabay (vectors), Flaticon, Noun ProjectSVG preferredBackgroundsUnsplash, Pixabay (backgrounds category)High resolution
raw or full size for print/publicationinclude_images - When extracting web content, request imagesSet these in your shell environment or .env file:
bash
# Free Stock Photos
UNSPLASH_ACCESS_KEY="" # https://unsplash.com/developers
PEXELS_API_KEY="" # https://www.pexels.com/api/
PIXABAY_API_KEY="" # https://pixabay.com/api/docs/
FLICKR_API_KEY="" # https://www.flickr.com/services/apps/
# Search Engines
GOOGLE_API_KEY="" # https://developers.google.com/custom-search
GOOGLE_CX="" # Custom Search Engine ID
BING_API_KEY="" # https://www.microsoft.com/en-us/bing/apis/
# News
NEWSAPI_KEY="" # https://newsapi.org
GNEWS_API_KEY="" # https://gnews.io
# AI Generation
GEMINI_API_KEY="" # https://aistudio.google.com
OPENAI_API_KEY="" # https://platform.openai.com