query
Find photos by applying filters such as album, keyword, person, date range, location, and more. Returns matching photo summaries with UUIDs for further actions.
Instructions
Use when: you need to find photos matching one or more filters — album, keyword, person, ML label, place, GPS radius (near), folder, taken-date or import-date range (addedAfter/addedInLast for 'recently imported'), year, file size, media type (screenshot, screen recording, selfie, panorama, live, portrait, time-lapse, slow-mo, burst, video), aesthetic score (minScore), OCR-detected text (detectedText), favorite/hidden flags, or title/description substrings — and get back a list of matches. This is the primary search/discovery tool; start here when you don't already have a UUID. Hidden photos are excluded unless hidden=true. Pass newestFirst=true with a limit to get the N most recent matches. Returns: count (the TOTAL number of matches), returned (the number of summaries in this response — capped at limit, default 500), and photo summaries (UUID, filename, date, dimensions, favorite/hidden/movie flags) — feed a UUID into get-photo/get-photos for full metadata, get-thumbnail to see it, or export to copy files. Do not use when: you already have UUIDs and want full metadata — use get-photo / get-photos; you want to see an image — use get-thumbnail; or you just want the catalog of album/keyword/person names — use list-albums / list-keywords / list-persons.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| live | No | Only live photos | |
| near | No | GPS-radius filter: "lat,lon,radiusKm" — only photos within radiusKm of the point (great-circle distance). Composes (AND) with every other filter. Requires location data: photos without GPS coordinates never match | |
| uuid | No | Specific UUIDs to fetch | |
| year | No | Taken in calendar year(s); ANY-match (e.g. [2024, 2025]) | |
| album | No | Album name(s); ANY-match | |
| burst | No | Only burst photos | |
| label | No | ML classification label(s) from Photos object detection (the labels field of get-photo, e.g. Dog, Beach, Text); ANY-match, exact whole-string | |
| limit | No | Cap the number of results returned (default 500 when omitted; count still reports the total matches) | |
| place | No | Place-name substring(s) from reverse geocoding (city, region, landmark). NOTE: multiple values are ANDed, not ORed — a photo must match every value | |
| title | No | Substring match on title | |
| video | No | Only videos/movies (alias of movies) | |
| folder | No | Folder name(s)/path(s) — matches photos in albums that live inside the folder; ANY-match (see list-folders for names) | |
| hidden | No | Only hidden photos | |
| movies | No | Include movies | |
| person | No | Person name(s); ANY-match | |
| photos | No | Include still photos | |
| selfie | No | Only selfies (front-camera photos) | |
| slowMo | No | Only slow-motion videos | |
| toDate | No | ISO 8601 upper bound on photo date. A bare date (e.g. 2025-06-30) includes that whole day; pass a full datetime (e.g. 2025-06-30T18:00:00) for a precise exclusive bound | |
| keyword | No | Keyword(s); ANY-match | |
| library | No | Path to a .photoslibrary (default: system Photos library) | |
| maxSize | No | Original file size at most this many bytes | |
| minSize | No | Original file size at least this many bytes | |
| favorite | No | Only favorites | |
| fromDate | No | ISO 8601 lower bound on photo date | |
| minScore | No | Only photos whose Photos-computed overall aesthetic score (0–1) is at least this — e.g. 0.7 for 'the good ones'. Post-filter over the other filters' matches; photos without a computed score never match | |
| panorama | No | Only panoramas | |
| portrait | No | Only portrait-mode (depth-effect) photos | |
| noKeyword | No | Only photos carrying no keyword at all | |
| notHidden | No | Exclude hidden photos (default behavior) | |
| timelapse | No | Only time-lapse videos | |
| addedAfter | No | ISO 8601 inclusive lower bound on IMPORT date (dateAdded — when the photo entered the library, not when it was taken) | |
| screenshot | No | Only screenshots | |
| addedBefore | No | ISO 8601 upper bound on IMPORT date. A bare date includes that whole day; a full datetime is a precise exclusive bound | |
| addedInLast | No | Imported within the trailing duration — "<number><unit>", unit s(econds) / m(inutes) / h(ours) / d(ays) / w(eeks), e.g. "7d" or "24h". The natural way to express "recently imported" | |
| description | No | Substring match on description | |
| hasLocation | No | true = only photos WITH GPS coordinates; false = only photos WITHOUT; omit for no location filter | |
| newestFirst | No | Sort matches by taken date, newest first, BEFORE limit is applied — so limit means 'the N most recent matches' instead of 'N in database order' | |
| notFavorite | No | Exclude favorites | |
| detectedText | No | Case-insensitive substring match over the text Photos' own OCR indexed in each photo (macOS 13+) — receipts, signs, screenshots. Post-filter that reads per-photo search info over every other filter's matches, so combine it with narrowing filters (dates, album) on big libraries | |
| screenRecording | No | Only screen recordings |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| photos | No | ||
| returned | No |