Stock Photo APIs — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Stock Photo APIs (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.
Wire stock imagery into a product through the three main free APIs - Unsplash, Pexels, Pixabay - without tripping the compliance rules that get API keys revoked. The fetch is trivial; the contractual obligations (Unsplash's download-endpoint trigger, Pixabay's mandatory caching, attribution everywhere) are the actual work, and skipping them is the #1 reason apps get deactivated.
| Provider | Auth | Search endpoint | Default rate limit | The gotcha most people miss |
|---|---|---|---|---|
| Unsplash | Authorization: Client-ID ACCESS_KEY | GET /search/photos | Demo 50 req/hr; Production 5000 req/hr after app review | MUST trigger the per-photo download endpoint on use, attribute photographer + Unsplash with UTM links, and hotlink the returned urls (do not rehost) |
| Pexels | Authorization: API_KEY | GET /v1/search | 200 req/hr, 20,000 req/mo default | Show Pexels + photographer attribution; do not build a Pexels clone; respect the X-Ratelimit-* response headers |
| Pixabay | ?key=API_KEY query param | GET /api/ | ~100 req/min | Must cache/download images to your own server per their terms rather than permanently hotlinking; cache API responses ~24h |
These are the documented defaults - confirm current limits and terms in each provider's live docs before shipping, since providers revise them.
Unsplash's guidelines are strict and enforced. The three non-negotiables: hotlink, trigger-download, attribute.
const ACCESS_KEY = process.env.UNSPLASH_ACCESS_KEY!; // server-side only
const H = { Authorization: `Client-ID ${ACCESS_KEY}` };
// 1. Search. Hotlink the urls Unsplash returns; do not rehost the file.
async function searchPhotos(query: string) {
const res = await fetch(
`https://api.unsplash.com/search/photos?query=${encodeURIComponent(query)}&per_page=12&orientation=landscape`,
{ headers: H },
);
if (!res.ok) throw new Error(`Unsplash ${res.status}`);
const { results } = await res.json();
return results; // each has urls.regular, links.download_location, user{name, links.html}
}
// 2. REQUIRED: when a photo is actually used/downloaded, ping its
// download_location. This is how photographers get credited usage.
// Skipping it is the top reason Unsplash deactivates apps.
async function triggerDownload(downloadLocation: string) {
await fetch(downloadLocation, { headers: H });
}
// 3. REQUIRED: attribute with UTM params to the photographer and Unsplash.
function attribution(photo: { user: { name: string; links: { html: string } } }) {
const u = `${photo.user.links.html}?utm_source=your_app&utm_medium=referral`;
return `Photo by <a href="${u}">${photo.user.name}</a> on ` +
`<a href="https://unsplash.com/?utm_source=your_app&utm_medium=referral">Unsplash</a>`;
}searchImages(query): Promise<Image[]>) so callers never depend on a provider's response shape, and a provider swap is one adapter.Produce a working integration containing: the server-side proxy with secret key handling, the provider adapter(s) behind a normalized interface, the Unsplash download-trigger call sited at the moment of use, attribution rendering, response caching per provider rule, and stored metadata (provider, ID, photographer, attribution HTML) for every persisted image.
License permission and model/property-release questions go to image-license-rights (and to counsel for anything contractual). Source selection and search strategy go to stock-photo-finder; visual selection among results to visual-asset-curation.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.