Skip to content

PixabayMediaClient

PixabayMediaClient implements the same provider-neutral MediaClient contract against the Pixabay API. Use it for photo and video search with Pixabay-specific filters (category, dimensions, editor's choice) when Pexels curated content or Pexels-only filters are not required.

Installation

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

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

Constructor

The constructor mirrors PexelsMediaClient: ApiKeyProvider plus optional cache and httpClient.

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

Authentication difference: Pixabay sends the API key as a key= query parameter on every request, not an Authorization header. You still wrap the key in ApiKeyProvider — the client handles wire formatting.

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

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

const client = new PixabayMediaClient(
  new ApiKeyProvider(process.env.PIXABAY_API_KEY!),
  { cache: new MemoryCache(120_000) },
);

In browser apps (Vite), use import.meta.env.VITE_PIXABAY_API_KEY.

MediaClient methods

MethodPixabay support
searchPhotos(params)
searchVideos(params)
getPhoto(id)
getVideo(id)
getCuratedPhotos(params?)❌ throws UNSUPPORTED_CAPABILITY
on / trackView / trackDownload
ts
import {
  ApiKeyProvider,
  PixabayMediaClient,
} from "@media-sdk/core";

const client = new PixabayMediaClient(
  new ApiKeyProvider(process.env.PIXABAY_API_KEY!),
);

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

console.log(result.items);
console.log(result.pagination);
ts
const result = await client.searchPhotos({
  query: "nature",
  page: 1,
  perPage: 20,
  photoFilters: {
    orientation: "landscape",
    color: "green",        // maps to Pixabay `colors` param
    category: "nature",
    minWidth: 1920,
    minHeight: 1080,
    editorsChoice: true,
    locale: "en",
  },
});
ts
const videos = await client.searchVideos({
  query: "ocean",
  page: 1,
  perPage: 15,
  videoFilters: {
    category: "nature",
    minWidth: 1280,
    minHeight: 720,
    editorsChoice: true,
  },
});

Single media

ts
const photo = await client.getPhoto(12345);
const video = await client.getVideo(67890);

Curated photos

Pixabay has no curated-photos endpoint. Calling getCuratedPhotos() throws:

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

try {
  await client.getCuratedPhotos({ page: 1, perPage: 20 });
} catch (error) {
  if (error instanceof MediaError) {
    console.error(error.code); // "UNSUPPORTED_CAPABILITY"
  }
}

Guard with capabilities instead of catching:

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

const caps = getCapabilities(client);

if (caps.operations.curatedPhotos) {
  // never true for PixabayMediaClient
}

Supported filters

FilterPhotosVideos
orientation
size
color
category
minWidth / minHeight
editorsChoice
locale

Passing an unsupported filter (for example size on photo search) throws UNSUPPORTED_FILTER. See Filters.

Color values

PhotoSearchFilters.color accepts both Pexels and Pixabay color enums. Pixabay adds values such as grayscale and transparent. Invalid values for the active provider throw INVALID_FILTER_VALUE.

Video rendition mapping

Pixabay video hits are normalized into VideoFile entries for each available rendition:

Pixabay renditionVideoFile.quality
large"large"
medium"medium"
small"small"
tiny"tiny"

Each file includes link, width, height, and fileType: "video/mp4".

Hotlinking requirement

Pixabay requires serving images and videos from the URLs returned by the API (previewURL, webformatURL, largeImageURL, video rendition URLs). Do not download and re-host media on your own CDN — use the normalized Photo.src and Video.videoFiles links directly.

Caching compliance

The SDK caches API JSON responses in memory (same as Pexels). Pixabay's terms restrict how long you may cache API responses. Tune MemoryCache TTL or inject a custom Cache implementation if your usage requires stricter compliance:

ts
import { MemoryCache, PixabayMediaClient } from "@media-sdk/core";

const client = new PixabayMediaClient(auth, {
  cache: new MemoryCache(30_000), // shorter TTL
});

Pagination

Pixabay computes hasNext / hasPrevious from page, perPage, and totalHits. Unlike Pexels, nextPage and prevPage URL fields are not populated. Use page numbers for navigation. See Pagination.

Capabilities

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

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

Next steps