Claude Code skill for searching and downloading stock images from Pexels, Unsplash, and Pixabay
SaferSkills independently audited stock-images (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
ps aux). Be aware of this inherent API limitation. Never display the full Pixabay curl command in output.images.pexels.comimages.unsplash.com, plus.unsplash.compixabay.com, cdn.pixabay.comlinks.download URL (not urls.raw) to comply with Unsplash API TOS (triggers download count)Do NOT activate this skill when:
<img>, next/image, etc.)Before searching, check if API keys are configured:
test -f ~/.config/stock-images/keys.json && stat -f "%Lp" ~/.config/stock-images/keys.json 2>/dev/null || stat -c "%a" ~/.config/stock-images/keys.json 2>/dev/nullchmod 600600: warn the user and offer to fix with chmod 600 ~/.config/stock-images/keys.json.Determine configured providers without printing secret values:
python3 - <<'PY'
import json
from pathlib import Path
config = Path.home() / ".config" / "stock-images" / "keys.json"
data = json.loads(config.read_text())
providers = [
name for name in ("pexels", "unsplash", "pixabay")
if data.get(name) and not str(data[name]).startswith("YOUR_")
]
print("\n".join(providers))
PYParse the JSON to determine which providers are configured (have non-empty, non-placeholder values). At least one provider is required.
Extract from the user's request:
Keep the parsed search results and metadata available for follow-up requests in the same conversation. If the user later says "download image #3", map that number back to the exact provider, image URL, download URL, author, author profile, and attribution data from the presented results.
Run curl commands for each configured provider. When multiple providers are configured, run them in parallel (separate Bash tool calls).
curl -sS -G --max-time 15 --fail "https://api.pexels.com/v1/search" \
--data-urlencode "query=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-H "Authorization: PEXELS_KEY"Response fields:
photos[].src.original — full image URLphotos[].src.medium — thumbnailphotos[].photographer — author namephotos[].photographer_url — author profilephotos[].width, photos[].height — dimensionscurl -sS -G --max-time 15 --fail "https://api.unsplash.com/search/photos" \
--data-urlencode "query=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-H "Authorization: Client-ID UNSPLASH_KEY"Response fields:
results[].urls.raw — full image URLresults[].urls.small — thumbnailresults[].user.name — author nameresults[].user.links.html — author profileresults[].links.download — download URL (use this for downloads, not urls.raw)results[].width, results[].height — dimensionscurl -sS -G --max-time 15 --fail "https://pixabay.com/api/" \
-d "key=PIXABAY_KEY" \
--data-urlencode "q=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-d "image_type=photo"Pixabay-specific: map "landscape" → "horizontal", "portrait" → "vertical". Minimum per_page is 3.
Response fields:
hits[].largeImageURL — full image URLhits[].previewURL — thumbnailhits[].user — author namehits[].user_id — for building profile URL: https://pixabay.com/users/USER-USER_ID/hits[].imageWidth, hits[].imageHeight — dimensionshits[].tags — descriptionPresent results in the user's language. Format:
## Results for "query" (N images)
### Provider Name
1. "Image Title/Description" — by [Author Name](author_profile_url)
URL: https://...
Resolution: WxHAfter presenting, ask if the user wants to download any of them.
When the user selects an image to download:
https:// and match an allowed domainlinks.download URL from search results instead of urls.raw to comply with Unsplash API TOS (this triggers their download counter)./images/ in current project directory. Ask for confirmation if the directory doesn't exist before creating it.<query-slug>-<provider>.<ext> (e.g., mountain-landscape-pexels.jpg). Default extension is .jpg unless the URL clearly indicates otherwise (.png, .webp).curl -sL --max-time 30 --fail -o "./images/FILENAME" "IMAGE_URL"ls -lh "./images/FILENAME"Attribution required: Photo by [Author](author_url) on [Provider]Alert if file size > 10MB — the user may want a smaller resolution.
Attribution and license requirements vary by provider and project use. Always preserve and present author attribution metadata so the user can comply with the relevant provider terms.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.