Skip to content

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

bash
pnpm add @media-sdk/core@^0.3.0

Sign up for a free API key at pexels.com/api.

Constructor

PexelsMediaClient accepts an ApiKeyProvider and optional client options:

OptionTypeDefaultDescription
cacheCacheMemoryCache (60s TTL)In-memory cache with request deduplication
httpClientHttpClientFetchHttpClientCustom transport for testing or proxying

Authentication uses an Authorization header. ApiKeyProvider supplies the key; the internal HTTP client sends it on every request.

ts
import {
  ApiKeyProvider,
  PexelsMediaClient,
} from "@media-sdk/core";

const auth = new ApiKeyProvider(process.env.PEXELS_API_KEY!);
const client = new PexelsMediaClient(auth);
ts
import {
  ApiKeyProvider,
  MemoryCache,
  PexelsMediaClient,
} from "@media-sdk/core";

const client = new PexelsMediaClient(
  new ApiKeyProvider(process.env.PEXELS_API_KEY!),
  { cache: new MemoryCache(120_000) },
);
ts
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:

MethodDescription
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.

ts
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);  // Pagination
ts
const result = await client.searchPhotos({
  query: "mountains",
  page: 1,
  perPage: 20,
  photoFilters: {
    orientation: "landscape",
    size: "large",
    color: "green",
    locale: "en-US",
  },
});
ts
const controller = new AbortController();

const result = await client.searchPhotos({
  query: "ocean",
  page: 1,
  perPage: 20,
  signal: controller.signal,
});

// controller.abort(); // cancels the in-flight search
ts
const result = await client.searchVideos({
  query: "ocean",
  page: 1,
  perPage: 15,
  videoFilters: {
    orientation: "landscape",
    size: "medium",
    locale: "en-US",
  },
});

Single media

ts
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:

ts
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.

FilterPhotosVideos
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:

ts
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:

ts
import { getCapabilities } from "@media-sdk/core";

const caps = getCapabilities(client);
// caps.operations.curatedPhotos === true
// caps.photoFilters.size === true

Next steps