Skip to content

Filters

Search filters let you narrow photo and video results by orientation, size, color, category, dimensions, and more. Filters are capability-gated per provider — unsupported filters throw MediaError and are never silently ignored.

Installation

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

Filter types

PhotoSearchFilters

ts
interface PhotoSearchFilters {
  orientation?: "landscape" | "portrait" | "square";
  size?: "large" | "medium" | "small";
  color?: PhotoColor | PixabayColor;
  category?: string;
  minWidth?: number;
  minHeight?: number;
  editorsChoice?: boolean;
  locale?: string;
}

VideoSearchFilters

ts
interface VideoSearchFilters {
  orientation?: "landscape" | "portrait" | "square";
  size?: "large" | "medium" | "small";
  category?: string;
  minWidth?: number;
  minHeight?: number;
  editorsChoice?: boolean;
  locale?: string;
}

Pass filters on SearchParams via photoFilters or videoFilters:

ts
await client.searchPhotos({
  query: "mountains",
  page: 1,
  perPage: 20,
  photoFilters: { orientation: "landscape" },
});

await client.searchVideos({
  query: "ocean",
  page: 1,
  perPage: 15,
  videoFilters: { orientation: "landscape", size: "medium" },
});

Provider mapping

Each client maps supported filter fields to its wire API. Unsupported fields throw before the HTTP request is sent.

FilterPexels photosPexels videosPixabay photosPixabay videos
orientation
size
color
category
minWidth / minHeight
editorsChoice
locale

See the provider comparison matrix for the full capability table.

Examples by provider

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

const pexels = new PexelsMediaClient(
  new ApiKeyProvider(process.env.PEXELS_API_KEY!),
);

await pexels.searchPhotos({
  query: "mountains",
  page: 1,
  perPage: 20,
  photoFilters: {
    orientation: "landscape",
    size: "large",
    color: "green",
    locale: "en-US",
  },
});
ts
import { ApiKeyProvider, PixabayMediaClient } from "@media-sdk/core";

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

await pixabay.searchPhotos({
  query: "nature",
  page: 1,
  perPage: 20,
  photoFilters: {
    orientation: "landscape",
    color: "green",
    category: "nature",
    minWidth: 1920,
    minHeight: 1080,
    editorsChoice: true,
    locale: "en",
  },
});
ts
await pexels.searchVideos({
  query: "ocean",
  page: 1,
  perPage: 15,
  videoFilters: {
    orientation: "landscape",
    size: "medium",
    locale: "en-US",
  },
});

Capability-gated UI

Check getCapabilities before sending user-selected filters. Build the filter object from flags that are true:

ts
import {
  getCapabilities,
  type MediaClient,
  type PhotoSearchFilters,
} from "@media-sdk/core";

async function searchWithFilters(
  client: MediaClient,
  query: string,
  ui: {
    orientation?: PhotoSearchFilters["orientation"];
    size?: PhotoSearchFilters["size"];
    category?: string;
  },
) {
  const caps = getCapabilities(client);
  const photoFilters: PhotoSearchFilters = {};

  if (ui.orientation && caps.photoFilters.orientation) {
    photoFilters.orientation = ui.orientation;
  }
  if (ui.size && caps.photoFilters.size) {
    photoFilters.size = ui.size;
  }
  if (ui.category && caps.photoFilters.category) {
    photoFilters.category = ui.category;
  }

  return client.searchPhotos({
    query,
    page: 1,
    perPage: 20,
    photoFilters,
  });
}

In React, use useMediaCapabilities — hooks forward photoFilters / videoFilters to core without stripping unsupported keys, so capability checks belong in your UI layer.

Error codes

Filters fail fast with typed errors. The SDK never silently ignores an unsupported or invalid filter.

UNSUPPORTED_FILTER

Thrown when a filter key is not supported by the active provider or media type:

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

try {
  await pixabay.searchPhotos({
    query: "nature",
    photoFilters: { size: "large" }, // Pixabay photos do not support size
  });
} catch (error) {
  if (error instanceof MediaError && error.code === "UNSUPPORTED_FILTER") {
    console.error("Filter not supported:", error.message);
    // Filter "size" is not supported by this provider
  }
}

INVALID_FILTER_VALUE

Thrown when a filter key is supported but the value is invalid for that provider:

ts
try {
  await pexels.searchPhotos({
    query: "nature",
    photoFilters: { color: "grayscale" }, // Pexels-only color set
  });
} catch (error) {
  if (error instanceof MediaError && error.code === "INVALID_FILTER_VALUE") {
    console.error("Invalid filter value:", error.message);
  }
}

Branch on error.code, not error.message. See Errors.

Anti-patterns

ts
// ❌ Do not strip filters silently based on provider name
if (provider === "pixabay") {
  delete filters.size;
}

// ✅ Gate on capabilities
if (!caps.photoFilters.size) {
  delete filters.size;
}
ts
// ❌ Do not send filters hoping the client ignores them
await client.searchPhotos({
  query: "nature",
  photoFilters: { size: "large" }, // throws on Pixabay
});

// ✅ Check capabilities first, or handle UNSUPPORTED_FILTER