Skip to main content

pexafy-python

Python client for the Pexafy image search API. Search a catalogue of free stock photos by describing what you want, or by handing it an image to match.

pip install pexafy

Getting started

from pexafy import Client

client = Client("your-api-key")

for photo in client.search("a quiet street in the rain", per_page=5):
    print(photo.urls.regular, "-", photo.alt_text)

The key comes from your dashboard; the free tier does not ask for a card. If you would rather not put it in the code, the client picks up PEXAFY_API_KEY from the environment.

Writing queries

Search runs on meaning, not keywords, so full sentences work better than a pile of nouns. two people hiking on a ridge at dawn finds what you would expect; hiking dawn people gives you a worse ranking, because you have thrown away the relationships between the words.

Filters narrow the result set after the semantic match:

result = client.search(
    "an empty office at night",
    orientation="landscape",
    color_name="blue",
    source=["Pexels", "Unsplash"],
    per_page=20,
)

print(len(result), "photos in", result.took_ms, "ms")

orientation, source and license_type take several values, as a list or as a comma separated string. color_name takes one: the API filters on a single colour, and passing more raises rather than quietly filtering on whichever one arrived last.

Paging

A single call returns one page. iter_search follows the cursor for you and yields photos until the results run out or you have seen enough:

for photo in client.iter_search("vintage typewriter", max_results=200):
    download(photo.urls.large)

Search by image

Pass a path, raw bytes, or an open file:

similar = client.search_by_image("moodboard/reference.jpg", per_page=12)

If you already have a photo id, client.similar(photo_id) is cheaper — the image does not have to be uploaded and encoded again.

Async

The same surface, awaitable:

import asyncio
from pexafy import AsyncClient

async def main():
    async with AsyncClient() as client:
        pages = await asyncio.gather(
            client.search("desert road"),
            client.search("snow covered pines"),
        )
    for page in pages:
        print(len(page))

asyncio.run(main())

Errors

Everything raised inherits from PexafyError. The ones worth catching separately:

from pexafy import errors

try:
    client.search("...")
except errors.RateLimitError as exc:
    time.sleep(exc.retry_after or 60)
except errors.AuthenticationError:
    ...          # key is missing, malformed or revoked
except errors.APIError as exc:
    print(exc.status_code, exc.code, exc.request_id)

request_id is worth logging. It is the fastest way to get an answer if you need to ask about a specific call.

Timeouts and 5xx responses are retried twice with backoff, and Retry-After is honoured when the server sends it. Set max_retries=0 if you would rather handle that yourself.

Command line

$ pexafy search "morning fog over pine trees" -n 3
0.847  019e0eb8-b028-73cb-9296-dfa70f557bc9   4000x2667   green      Pexels     https://...
0.812  019e4c9b-3022-7660-b43d-e730b8435f24   6000x4000   green      Unsplash   https://...
0.798  019e4f39-66d4-7ef2-bc9b-eb5340fd243e   3648x5472   grey       Pexels     https://...

pexafy photo <id>, pexafy similar <id> and pexafy usage are also there. Add --json to any of them for the raw response.

Attribution

Photos come from several providers with different licence terms. Every photo carries an attribution object with a ready made credit line:

photo.attribution.plain   # Photo by J. Doe
photo.attribution.html    # <a href="...">J. Doe</a>

Check photo.license_type if your use depends on it.

Reference

Method What it does
search(q, **filters) one page of results
iter_search(q, max_results=None, **filters) every page, cursor handled
search_by_image(image, **filters) match an image you supply
get_photo(photo_id) one photo by id
similar(photo_id, **filters) photos close to an existing one
colors() sources() orientations() licenses() filter values you can use
suggest_photographers(q) photographer(username) photographer lookup
collections() create_collection(name) add_to_collection(id, photo_id) saved sets
usage() usage_daily() usage_monthly() usage_by_key() where you are against your quota

Full API documentation is at docs.pexafy.com.

Requirements

Python 3.9 or newer. The only dependency is httpx.

Licence

MIT.

Metadata

Release files for pexafy 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pexafy 0.1.2
File Size Uploaded
pexafy-0.1.2.tar.gz 17.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pexafy 0.1.2
File Interpreter ABI Platform
pexafy-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 32.4 kB

Release files / pexafy-0.1.2.tar.gz

Download URL pexafy-0.1.2.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
e46faa222be3c88b874a684a7cddce133b52816fb71fc51dfb7047ad4889f179
BLAKE2b-256 checksum
How to use checksums
26198cf1a8f14265167dba825f84bc78e090d941ea4e0e81df59fb557f199002
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / pexafy-0.1.2-py3-none-any.whl

Download URL pexafy-0.1.2-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3797c575288c87f6fd85e8e28af87e5bdba521dee857bf7ca371def9aa4b3ff0
BLAKE2b-256 checksum
How to use checksums
bc8539abed81e5189c9b869345d43f1332783988d1c360d5b95c903543a5405b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page