# Find Me A Museum Image

> Find and download real, non-AI, public-domain artwork from museum open-access collections (The Met, Art Institute of Chicago, Cleveland Museum of Art, Rijksmuseum, Getty, SMK, Smithsonian) without leaving the CLI. Use when the user wants an image, artwork, painting, hero image, background, or visual for their project and prefers real art over AI-generated or stock imagery — e.g. "find me a painting for the landing page", "I need a public domain image of the sea", "get me some Monet for the header".

- Skill: `stevysmith/find-me-a-museum-image` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add stevysmith/find-me-a-museum-image`
- Raw SKILL.md: https://api.skillmd.com/api/skills/stevysmith/find-me-a-museum-image/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: stevysmith (https://skillmd.com/u/stevysmith)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/stevysmith/find-me-a-museum-image

---


# Find me a museum image

Search museum open-access APIs for public-domain (CC0) artwork, preview candidates visually, and download a high-resolution image into the user's project with attribution — all from the CLI.

The tool is `scripts/museum_image.py` inside this skill's directory — the directory containing this SKILL.md. Since your working directory is the user's project, call it by absolute path; `<skill-dir>` below means this skill's directory. Python 3, stdlib only. Museums that work with no API key: `artic` (Art Institute of Chicago), `met` (The Met), `cleveland` (Cleveland Museum of Art), `smk` (Statens Museum for Kunst, Denmark), `rijks` (Rijksmuseum), `getty` (J. Paul Getty Museum). With a free key in an env var: `smithsonian` (`SMITHSONIAN_API_KEY`).

## Workflow

### 1. Turn the request into search terms

Distill what the user actually needs:

- **Subject/mood**: "calm sea", "sunflowers", "storm", "city at night". Museum search is keyword-based — search concrete nouns and artist names, not vibes. Translate "something serene for a meditation app" into searches like `"calm sea"`, `"water lilies"`, `"quiet landscape"`, or artist names (`monet`, `hammershoi`, `hiroshige`).
- **Orientation**: a hero/banner wants `--orientation landscape`; a mobile splash wants `portrait`.
- **Usage context**: where in the project will it go? This decides the output path and how picky to be about palette.

Run 2–4 different queries rather than one — museum metadata is sparse, and synonyms surface different works.

### 2. Search with thumbnails

```bash
python3 <skill-dir>/scripts/museum_image.py search "water lilies" \
  --orientation landscape --limit 6 \
  --save <scratchpad>/results.json --thumbs <scratchpad>/thumbs
```

Replace `<scratchpad>` with your session's scratchpad directory (or any temp dir) — these are working files, not project files. `--limit` is per museum, so `--limit 6` can return ~35 results across the six keyless museums; 4–6 is a good range. Give each query its own files (`results2.json`, `thumbs2/`) — thumbnail names restart at `00_` every run, so reusing a thumbs dir mixes artworks from different queries. Results are numbered; thumbnails land as `NN_museum.jpg`.

### 3. Curate visually — this is the key step

**Read the downloaded thumbnail images** (the Read tool renders them). Judge them against the user's actual need: palette, mood, composition, whether text would overlay legibly. Metadata cannot tell you a painting is muddy brown; your eyes can. Discard weak candidates and, if nothing sings, run another query with different terms before settling.

### 4. Present a shortlist

Show the user the best 2–4 candidates: title, artist, date, museum, dimensions, and the museum page URL. If the user asked you to just pick one, pick the best match and say why.

### 5. Download at full resolution

```bash
python3 <skill-dir>/scripts/museum_image.py download <scratchpad>/results.json 3 \
  --out assets/hero.jpg
```

This fetches the highest practical resolution (Cleveland's multi-hundred-MB native TIFF is deliberately skipped; its URL is in the results JSON as `full_tiff_url` if anyone truly wants it) and writes an `*.attribution.json` sidecar next to it (title, artist, museum, license, source URL). Put the image where the project keeps static assets (`public/`, `assets/`, `static/` — check first). Full-res museum scans can be 5–50 MB; if the project needs a smaller file, resize a copy (e.g. `sips -Z 2400 out.jpg` on macOS) but keep the sidecar accurate.

### 6. Attribution

CC0/public-domain images require no credit, but crediting is good practice. Offer the user the suggested credit line the download prints, e.g.:

> Claude Monet, "Low Tide at Pourville" (1882). The Cleveland Museum of Art. Public Domain (CC0).

If the image goes on a public page, suggest a caption or an HTML comment near the asset reference.

## Sharp edges

- **Trust the license field, not assumptions.** The script already filters to public-domain/CC0 works, but if you fetch museum data by hand, check the rights field before using an image — most museums also serve *copyrighted* works through the same APIs.
- The Met search is the slowest (it needs one request per candidate object), and its image index is stale — a search can return hits whose objects turn out non-PD or imageless, so Met sometimes contributes fewer results than other museums. Normal, not a bug.
- If a museum errors or times out, the search continues without it — warnings go to stderr. Don't treat a single museum failure as a task failure.
- `--orientation` filters on known dimensions: artic, cleveland, smk, rijks, and getty report real pixel dims; met uses the artwork's physical proportions as a proxy; smithsonian rows pass through unfiltered. A stderr note tells you how many results dodged the filter — confirm those from their thumbnails.
- **Jurisdiction caveat**: museum public-domain labels follow US rules (published before ~1930). A 1929 Picasso etching can be CC0 at a US museum yet still copyrighted in life+70 countries. For a user shipping to an international audience, prefer artists who died 70+ years ago — when in doubt, mention it.
- Empty results usually mean the query is too specific. Broaden it ("impressionist coast" → "coast"), try an artist name, or drop `--orientation` (works with unknown dimensions are never filtered out, but known-wrong ones are).
- Rijksmuseum has no free-text search — the script queries its `creator` and `title` fields, so subject words work poorly there; artist names work well. Titles come back in Dutch.
- SMK's search is fuzzy: "monet" matches the Danish island "Møn" (SMK owns no Monet). Judge SMK hits by their thumbnails, not by faith in the keyword match.
- Getty search results omit medium/dimensions — that's why those columns are sometimes blank for `getty` rows.
- Smithsonian needs a free instant key from https://api.data.gov/signup/ (`SMITHSONIAN_API_KEY`). Only mention it if the user wants that collection; six museums already work with no key.
- More API detail (endpoints, field maps, image URL recipes, verified gotchas) lives in `references/apis.md` if you need to query a museum directly — including a recipe for National Gallery of Art, which has no live search API but does have an open IIIF server.

