PexelsMediaClient
PexelsMediaClient implements the provider-neutral MediaClient contract against the Pexels API. Use it when you need photo and video search, single-media lookups, curated photos, and Pexels-specific filters (orientation, size, color, locale).
Installation
pnpm add @media-sdk/core@^0.3.0Sign up for a free API key at pexels.com/api.
Constructor
PexelsMediaClient accepts an ApiKeyProvider and optional client options:
| Option | Type | Default | Description |
|---|---|---|---|
cache | Cache | MemoryCache (60s TTL) | In-memory cache with request deduplication |
httpClient | HttpClient | FetchHttpClient | Custom transport for testing or proxying |
Authentication uses an Authorization header. ApiKeyProvider supplies the key; the internal HTTP client sends it on every request.
import {
ApiKeyProvider,
PexelsMediaClient,
} from "@media-sdk/core";
const auth = new ApiKeyProvider(process.env.PEXELS_API_KEY!);
const client = new PexelsMediaClient(auth);import {
ApiKeyProvider,
MemoryCache,
PexelsMediaClient,
} from "@media-sdk/core";
const client = new PexelsMediaClient(
new ApiKeyProvider(process.env.PEXELS_API_KEY!),
{ cache: new MemoryCache(120_000) },
);import type { HttpClient } from "@media-sdk/core";
import {
ApiKeyProvider,
PexelsMediaClient,
} from "@media-sdk/core";
const httpClient: HttpClient = {
async get(url, options) {
const response = await fetch(url, {
headers: options?.headers,
signal: options?.signal,
});
return response.json();
},
};
const client = new PexelsMediaClient(
new ApiKeyProvider(process.env.PEXELS_API_KEY!),
{ httpClient },
);In browser apps (Vite), read the key from an environment variable such as import.meta.env.VITE_PEXELS_API_KEY.
MediaClient methods
All methods are defined on the shared MediaClient interface. Pexels supports every operation:
| Method | Description |
|---|---|
searchPhotos(params) | Search photos by query |
searchVideos(params) | Search videos by query |
getPhoto(id) | Fetch a single photo by ID |
getVideo(id) | Fetch a single video by ID |
getCuratedPhotos(params?) | Fetch Pexels-curated photos (Pexels-only) |
on(event, listener) | Subscribe to user-action events |
trackView(event) | Emit a view event (your app calls this) |
trackDownload(event) | Emit a download event (your app calls this) |
API methods fetch and normalize data only — they do not emit events automatically. See Events.
Photo search
import {
ApiKeyProvider,
PexelsMediaClient,
} from "@media-sdk/core";
const client = new PexelsMediaClient(
new ApiKeyProvider(process.env.PEXELS_API_KEY!),
);
const result = await client.searchPhotos({
query: "nature",
page: 1,
perPage: 20,
});
console.log(result.items); // Photo[]
console.log(result.pagination); // Paginationconst result = await client.searchPhotos({
query: "mountains",
page: 1,
perPage: 20,
photoFilters: {
orientation: "landscape",
size: "large",
color: "green",
locale: "en-US",
},
});const controller = new AbortController();
const result = await client.searchPhotos({
query: "ocean",
page: 1,
perPage: 20,
signal: controller.signal,
});
// controller.abort(); // cancels the in-flight searchVideo search
const result = await client.searchVideos({
query: "ocean",
page: 1,
perPage: 15,
videoFilters: {
orientation: "landscape",
size: "medium",
locale: "en-US",
},
});Single media
const photo = await client.getPhoto(12345);
const video = await client.getVideo(67890);Curated photos
getCuratedPhotos is a Pexels-only operation. It does not require a search query:
import { getCapabilities } from "@media-sdk/core";
const caps = getCapabilities(client);
if (caps.operations.curatedPhotos) {
const curated = await client.getCuratedPhotos({
page: 1,
perPage: 20,
});
console.log(curated.items);
}Always guard with getCapabilities when your app may swap providers at runtime.
Supported filters
Pexels photo filters: orientation, size, color, locale.
Pexels video filters: orientation, size, locale (no color).
Unsupported filters throw MediaError with code: "UNSUPPORTED_FILTER". Invalid enum values throw INVALID_FILTER_VALUE. See Filters.
| Filter | Photos | Videos |
|---|---|---|
orientation | ✅ | ✅ |
size | ✅ | ✅ |
color | ✅ | ❌ |
category | ❌ | ❌ |
minWidth / minHeight | ❌ | ❌ |
editorsChoice | ❌ | ❌ |
locale | ✅ | ✅ |
Pagination
Search and curated responses return a normalized pagination object. Pexels preserves raw nextPage / prevPage URL strings in addition to hasNext / hasPrevious:
const { items, pagination } = await client.searchPhotos({
query: "nature",
page: 1,
perPage: 20,
});
if (pagination.hasNext) {
const next = await client.searchPhotos({
query: "nature",
page: pagination.page + 1,
perPage: pagination.perPage,
});
}See Pagination for the full field reference and provider differences.
Capabilities
PexelsMediaClient exposes a readonly capabilities property. Use getCapabilities(client) for provider-neutral UI gating:
import { getCapabilities } from "@media-sdk/core";
const caps = getCapabilities(client);
// caps.operations.curatedPhotos === true
// caps.photoFilters.size === trueNext steps
- PixabayMediaClient — second built-in provider
- Provider comparison — capability matrix and when to pick each
- Filters — filter types and error codes
- Events —
trackView/trackDownloadfor analytics