Skip to main content
Glama
Pexafy

Pexafy Stock Photos

Official

Search free stock photos

search_photos
Read-only

Use this when the user asks for a real photograph, or states a need that a photograph fills, and the picture is not already in the conversation.

Instructions

Use this when the user asks for a real photograph, or states a need that a photograph fills, and the picture is not already in the conversation.

Call it when they ask outright: “find me photos of…”, “show me images of…”, “I need a picture of…”, “do you have a photo of…”, “where can I find free photos of…”, in any language. Call it when they describe the need without asking to search: “I'm writing an article and need a header image”, “my landing page needs a hero image”, “I need something to illustrate this”. Call it when they ask for something meant to carry photographs: “write an article with pictures”, “a deck with images”. Call it when they name only the picture, with no reason given: “a photo of a white mug”, “a train in Japan”. If the user is working on something that usually carries photographs — an article, a page, a deck, a post — without asking for any, you may offer to look for some; call it only once they accept.

This covers requests for photographs for articles, blog posts, websites, landing pages, products, slides, documents, reports, social posts, ads, newsletters, banners, thumbnails, covers, posters, backgrounds, wallpapers and mood boards; photographs that illustrate a concept, explain a subject or accompany a piece of writing; and any request for free, stock, royalty-free, commercially usable, real or documentary photographs.

A request for a visual is not always a request for a photograph: this tool finds photographs that already exist — not illustrations, drawings, logos, icons, diagrams or screenshots — and it does not generate, edit or upscale an image, nor look for a named person.

It searches Pexafy's own index of millions of free-to-use photographs from stock libraries such as Unsplash, Pexels and Pixabay, matched to the scene described. Each result carries a rank, a photo_id, its licence, the credit line to display and an image link.

Input Schema

NameRequiredDescriptionDefault
english_search_sentenceYesRequired. Describe the desired photograph in one concise English sentence, focusing on its visible subject and scene. Be specific: “Two colleagues laughing in a bright open-plan office” is more effective than “People office”. Keywords work too — send the user's own words, in English, rather than inventing detail they did not ask for. Maximum 250 characters. Describe one coherent scene, focusing on what should appear in the photograph rather than its intended use. Specify the requested photo shape or orientation in explicit_orientation_filter, not here. Example: “An old man sitting at a café table he has visited every morning for thirty years”.
explicit_orientation_filterNoOmit this parameter unless the user explicitly asks for a photo shape or orientation in their own words, or names a format whose shape is part of its definition — a vertical Short, a banner, a square post, a phone wallpaper. This is a hard filter, not a preference: it removes photos with other shapes before ranking, so using a shape the user did not request can exclude the best matches. Never infer the shape from a word inside `english_search_sentence` — “landscape” in “a natural landscape” names the scene, not the format — nor from the subject, the composition, or a purpose that fixes no shape (“a photo for my blog post”, “something for my landing page”). If you are choosing a value rather than repeating one explicitly requested by the user, omit it. Allowed values: `landscape`, `portrait`, `square`. Multiple values are allowed: two shapes return more than one alone, though any filter still returns less than none. For example, “anything but portrait” means `['landscape', 'square']`.

Output Schema

NameRequiredDescriptionDefault
dataNo
errorNo
budgetNoPresent only when the caller is near the end of an allowance — the daily one without an account, the monthly one with. What is left of it, and, for a caller with no account, the one sentence that says what lifts the limit. Also carried by a refusal, where it describes the wall itself.
noticeNoWhy this answer is empty, when it is. A plan limit was reached: the allowance and when it returns. There is nothing to retry until then.
successNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed11 schema fields changedv1.0.1
    • addedOutput schema / properties / data / items / properties / alt_description / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / alt_description / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / height / anyOf
      Added value: +[
      +  {
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / height / type
      Removed value: -[
      -  "integer",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / photographer_full_name / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / photographer_full_name / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / source_image_url / anyOf
      Added value: +[
      +  {
      +    "format": "uri",
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / source_image_url / format
      Removed value: -"uri"
    • removedOutput schema / properties / data / items / properties / source_image_url / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / width / anyOf
      Added value: +[
      +  {
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / width / type
      Removed value: -[
      -  "integer",
      -  "null"
      -]
  2. Changed39 schema fields changedv1.0.0
    • removedInput schema / properties / after_date
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Only return photos published on or after this date, formatted `YYYY-MM-DD`.",
      -  "example": "2025-01-01",
      -  "title": "After Date"
      -}
    • removedInput schema / properties / color_hex
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Keep only photos close to this hex color (e.g. `#1E90FF`). Cannot be combined with `color_name`. Use `color_tolerance` to widen or tighten the match.",
      -  "title": "Color Hex"
      -}
    • removedInput schema / properties / color_name
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Keep only photos whose dominant color matches one of: red, orange, yellow, green, blue, purple, pink, brown, black, white, gray, teal, beige, gold, navy. Cannot be combined with color_hex.",
      -  "example": "blue",
      -  "title": "Color Name"
      -}
    • removedInput schema / properties / color_tolerance
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "maximum": 255,
      -      "minimum": 0,
      -      "type": "integer"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "How far a photo's color may be from `color_hex` and still match, from `0` (exact match) to `255` (very loose). Defaults to `20`. Only applies when `color_hex` is set.",
      -  "title": "Color Tolerance"
      -}
    • removedInput schema / properties / cursor
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Token used to fetch the next page. Take the `pagination.next_cursor` value from a previous response and pass it back here. See the [Pagination](/pagination) guide.",
      -  "title": "Cursor"
      -}
    • addedInput schema / properties / english_search_sentence
      Added value: +{
      +  "description": "Required. Describe the desired photograph in one concise English sentence, focusing on its visible subject and scene.\n\nBe specific: “Two colleagues laughing in a bright open-plan office” is more effective than “People office”. Keywords work too — send the user's own words, in English, rather than inventing detail they did not ask for.\n\nMaximum 250 characters. Describe one coherent scene, focusing on what should appear in the photograph rather than its intended use.\n\nSpecify the requested photo shape or orientation in explicit_orientation_filter, not here.\n\nExample: “An old man sitting at a café table he has visited every morning for thirty years”.",
      +  "examples": [
      +    "two people sharing a bench in comfortable silence"
      +  ],
      +  "maxLength": 250,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / explicit_orientation_filter
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "enum": [
      +          "landscape",
      +          "portrait",
      +          "square"
      +        ],
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Omit this parameter unless the user explicitly asks for a photo shape or orientation in their own words, or names a format whose shape is part of its definition — a vertical Short, a banner, a square post, a phone wallpaper.\n\nThis is a hard filter, not a preference: it removes photos with other shapes before ranking, so using a shape the user did not request can exclude the best matches.\n\nNever infer the shape from a word inside `english_search_sentence` — “landscape” in “a natural landscape” names the scene, not the format — nor from the subject, the composition, or a purpose that fixes no shape (“a photo for my blog post”, “something for my landing page”). If you are choosing a value rather than repeating one explicitly requested by the user, omit it.\n\nAllowed values: `landscape`, `portrait`, `square`. Multiple values are allowed: two shapes return more than one alone, though any filter still returns less than none. For example, “anything but portrait” means `['landscape', 'square']`."
      +}
    • removedInput schema / properties / license_type
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "items": {
      -        "type": "string"
      -      },
      -      "type": "array"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Keep only photos with these license types: free, cc0. 'free' means the photo can be used freely and attribution is appreciated. Repeat the parameter to pass several.",
      -  "example": "free",
      -  "title": "License Type"
      -}
    • removedInput schema / properties / orientation
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "items": {
      -        "type": "string"
      -      },
      -      "type": "array"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Keep only photos with these shapes: landscape, portrait, square. Repeat the parameter to pass several.",
      -  "example": "landscape",
      -  "title": "Orientation"
      -}
    • removedInput schema / properties / photographer
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Only return photos from this photographer's username. Use `GET /api/v1/facets/photographers/suggest` to find usernames.",
      -  "example": "nasa",
      -  "title": "Photographer"
      -}
    • removedInput schema / properties / q
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "maxLength": 500,
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Your search query as a full natural-language sentence describing the scene you want — Pexafy is semantic, so sentences beat keywords. Up to 500 characters. Optional if you provide at least one filter instead. Example: 'an old man sitting at a café table he has visited every morning for thirty years'.",
      -  "example": "two people sharing a bench in comfortable silence",
      -  "title": "Q"
      -}
    • removedInput schema / properties / source
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "items": {
      -        "type": "string"
      -      },
      -      "type": "array"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "description": "Keep only photos from these providers: Unsplash, Pexels, Pixabay, Kaboompics, Burst, StockSnap, Picjumbo, Skitterphoto, NegativeSpace. Repeat the parameter to pass several.",
      -  "example": "Unsplash",
      -  "title": "Source"
      -}
    • changedInput schema / required
      Previous value: -[]New value: +[
      +  "english_search_sentence"
      +]
    • addedOutput schema / properties / budget
      Added value: +{
      +  "description": "Present only when the caller is near the end of an allowance — the daily one without an account, the monthly one with. What is left of it, and, for a caller with no account, the one sentence that says what lifts the limit. Also carried by a refusal, where it describes the wall itself.",
      +  "properties": {
      +    "limit": {
      +      "description": "Searches allowed in that period.",
      +      "type": "integer"
      +    },
      +    "message": {
      +      "description": "The whole notice in words, for a host with no UI.",
      +      "type": "string"
      +    },
      +    "remaining": {
      +      "description": "Searches left in that period.",
      +      "type": "integer"
      +    },
      +    "scope": {
      +      "description": "Which allowance this counts: the daily one or the monthly one. Both exist with or without an account, so `signed_in` does not tell them apart.",
      +      "enum": [
      +        "day",
      +        "month"
      +      ],
      +      "type": "string"
      +    },
      +    "signed_in": {
      +      "description": "Whether the caller has an account. False is the anonymous allowance.",
      +      "type": "boolean"
      +    },
      +    "state": {
      +      "description": "`warning` while there is room left, `exhausted` once there is none.",
      +      "enum": [
      +        "warning",
      +        "exhausted"
      +      ],
      +      "type": "string"
      +    },
      +    "used": {
      +      "description": "Searches spent in that period.",
      +      "type": "integer"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / data / items / description
      Previous value: -"A photo result. Fields returned can be narrowed with the `fields` parameter and may depend on your plan."New value: +"One photograph of this answer."
    • changedOutput schema / properties / data / items / properties / attribution / description
      Previous value: -"Ready-to-display credit for the photographer/source."New value: +"The credit line to display, already written."
    • removedOutput schema / properties / data / items / properties / attribution / properties / html
      Removed value: -{
      -  "description": "HTML attribution snippet.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / blur_hash
      Removed value: -{
      -  "description": "BlurHash placeholder string.",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / color_hex
      Removed value: -{
      -  "description": "Dominant color hex code.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / color_name
      Removed value: -{
      -  "description": "Dominant color name.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / description
      Removed value: -{
      -  "description": "AI-generated caption.",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / image_url
      Removed value: -{
      -  "description": "Canonical source image URL.",
      -  "format": "uri",
      -  "type": "string"
      -}
    • addedOutput schema / properties / data / items / properties / orientation / description
      Added value: +"The shape of this photograph — `landscape`, `portrait` or `square`, the values `explicit_orientation_filter` takes."
    • removedOutput schema / properties / data / items / properties / photographer_url
      Removed value: -{
      -  "format": "uri",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / photographer_username
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / data / items / properties / rank
      Added value: +{
      +  "description": "This photograph's place in this answer, from 1. A person may name a result by position (“the second one”); the tools take that result's `photo_id`, not its rank.",
      +  "type": "integer"
      +}
    • removedOutput schema / properties / data / items / properties / relevance_score
      Removed value: -{
      -  "description": "Match score 0–1 (higher is better). Only on search results.",
      -  "type": [
      -    "number",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / source_description
      Removed value: -{
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • changedOutput schema / properties / data / items / properties / source_image_url / description
      Previous value: -"URL of the photo's page on the provider."New value: +"The photograph's page on the library it came from — where to send someone who wants the source."
    • removedOutput schema / properties / data / items / properties / uploaded_on
      Removed value: -{
      -  "description": "Publication date (YYYY-MM-DD).",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • changedOutput schema / properties / data / items / properties / urls / description
      Previous value: -"Ready-to-use image links in five sizes."New value: +"The photograph's image file, 1280 pixels wide, for a page, a document or a download. `urls` carries this one variant and no other."
    • removedOutput schema / properties / data / items / properties / urls / properties / full
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / large
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / small
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / thumb
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • changedOutput schema / properties / error / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "code": {
      -        "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`).",
      -        "type": "string"
      -      },
      -      "message": {
      -        "description": "Human-readable error message.",
      -        "type": "string"
      -      },
      -      "request_id": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "code",
      -      "message"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "code": {
      +        "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`).",
      +        "type": "string"
      +      },
      +      "message": {
      +        "description": "Human-readable error message.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "code",
      +      "message"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / meta
      Removed value: -{
      -  "properties": {
      -    "request_id": {
      -      "description": "Unique id for this request (quote it in support tickets).",
      -      "type": "string"
      -    },
      -    "took_ms": {
      -      "description": "Server processing time in milliseconds.",
      -      "type": "number"
      -    }
      -  },
      -  "type": "object"
      -}
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Why this answer is empty, when it is. A plan limit was reached: the allowance and when it returns. There is nothing to retry until then.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / pagination
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "properties": {
      -        "has_more": {
      -          "description": "Whether another page exists.",
      -          "type": "boolean"
      -        },
      -        "next_cursor": {
      -          "description": "Pass back as `cursor` for the next page; `null` when `has_more` is false.",
      -          "type": [
      -            "string",
      -            "null"
      -          ]
      -        },
      -        "per_page": {
      -          "description": "Number of items per page.",
      -          "type": "integer"
      -        }
      -      },
      -      "type": "object"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
  3. First observedv0.2.0

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/openWorldHint/idempotentHint(false)/destructiveHint(false), so the safety profile is covered. The description adds genuinely useful context beyond them: the index is Pexafy's own corpus of free-to-use photos sourced from Unsplash, Pexels and Pixabay, and results carry a licence and a credit line that must be displayed. It slightly overlaps the output schema by listing result fields, and mentions no rate limits or failure behavior, keeping it at 4 rather than 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the primary condition ('Use this when...') and organized into triggers, scope and exclusions. It is long and several quoted example requests are near-duplicates, costing some efficiency, but every section serves routing or scope-setting rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter, read-only search tool whose safety annotations and output schema are both present, the description supplies everything an agent needs to decide to call it: triggers, exclusions, entity scope, and the fact that it is a hard-filtered, externally sourced search. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters carry rich guidance (max length, specificity advice, explicit orientation rules, multi-value semantics), so the baseline is 3. The description body itself adds only the loose framing that results are 'matched to the scene described' and carries no parameter-level detail of its own.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (finds/searches) and resource (existing free stock photographs matched to a described scene) and bounds it sharply: not illustrations, logos, icons, diagrams or screenshots, and no generation, editing, upscaling or named-person lookup. Combined with the parameter name `english_search_sentence`, an agent can distinguish this from the text-query sibling `search_photos_by_image` without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Enumerates concrete trigger phrasings, covers indirect needs ('my landing page needs a hero image'), and explicitly states when NOT to use it (illustrations, drawings, logos, icons, diagrams, screenshots, image generation/editing, named persons). It even specifies an offer-first-then-call-once protocol for working contexts that usually carry photos.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.