Skip to main content

Python client for the Unsplash API

Project description

Unsplash Client

Lightweight, typed Python client for the Unsplash API focusing on the photo search endpoint. Includes:

  • Async HTTP powered by httpx
  • Pydantic models for responses & request params
  • A fluent builder (UnsplashSearchParamsBuilder) for ergonomic query construction
  • Direct kwargs usage if you prefer no builder
  • Automatic retry on rate-limit responses (429) via the async_retry decorator

Installation

Requires Python 3.13+.

pip install unsplash-wrapper

Set your Unsplash access key (Create one in your Unsplash developer dashboard):

export UNSPLASH_API_KEY=your_access_key_here  # macOS/Linux
$env:UNSPLASH_API_KEY='your_access_key_here'  # PowerShell

Quick Start

from unsplash_client import UnsplashClient

client = UnsplashClient()  # Uses UNSPLASH_API_KEY from environment
response = await client.search_photos(query="mountains")

print("Total found:", response.total)
for photo in response.results:
	print(photo.id, photo.url)

Search Parameter Options

You can provide parameters in two styles: Builder or Raw kwargs.

1. Builder style

from unsplash_client import (
	UnsplashClient,
	UnsplashSearchParamsBuilder,
	Orientation,
	ContentFilter,
	OrderBy,
)

builder = (
	UnsplashSearchParamsBuilder()
	.with_query("sunset beach")
	.with_limit(20)
	.with_landscape_orientation()
	.with_high_quality()
	.with_order_by_latest()
	.with_page(2)
)

params = builder.build()
client = UnsplashClient()
response = await client.search_photos(params)

print(f"Returned {len(response.results)} of {response.total} total")

2. Direct kwargs style

All fields mirror the Pydantic model UnsplashSearchParams:

from unsplash_client import UnsplashClient, Orientation, ContentFilter, OrderBy

client = UnsplashClient()
response = await client.search_photos(
	query="architecture",
	per_page=15,
	orientation=Orientation.PORTRAIT,
	content_filter=ContentFilter.HIGH,
	page=1,
	order_by=OrderBy.RELEVANT,
)

for p in response.results:
	print(p.id, p.user.username)

Models Overview

from unsplash_client import UnsplashSearchResponse

# UnsplashSearchResponse fields:
# total: int               -> total matching results
# total_pages: int         -> number of pages available
# results: list[UnsplashPhoto]
#
# UnsplashPhoto exposes convenient properties like:
# photo.url (regular size URL)

Error Handling

The client raises typed exceptions from unsplash_client.exceptions:

  • UnsplashAuthenticationException – missing/invalid key (401)
  • UnsplashNotFoundException – resource not found (404)
  • UnsplashRateLimitException – rate limited (429) (contains retry_after if provided)
  • UnsplashServerException – server error 5xx
  • UnsplashClientException – other 4xx errors
  • UnsplashTimeoutException – request timed out

Example:

from unsplash_client import (
	UnsplashClient,
	UnsplashRateLimitException,
	UnsplashAuthenticationException,
)

client = UnsplashClient()

try:
	response = await client.search_photos(query="forest")
except UnsplashRateLimitException as e:
	if e.retry_after:
		print(f"Rate limited; retry after {e.retry_after}s")
	else:
		print("Rate limited; no retry window provided")
except UnsplashAuthenticationException:
	print("Invalid API key configured")

Retry Behavior

search_photos automatically retries 429 responses up to 3 times with exponential backoff (1s, 2s, 4s). Other errors fail fast.

Logging

The client uses a library-specific logger name: unsplash_client.UnsplashClient. Attach handlers or configure globally:

import logging

logging.basicConfig(level=logging.INFO)

Advanced: Custom Param Object

If you need to construct params manually (validation enforced):

from unsplash_client import UnsplashSearchParams, Orientation

params = UnsplashSearchParams(query="minimal", per_page=5, orientation=Orientation.SQUARISH)
client = UnsplashClient()
response = await client.search_photos(params)

Development

Run tests:

uv run pytest -q

Type check (if mypy configured):

mypy unsplash_client

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unsplash_wrapper-0.1.0.tar.gz (52.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unsplash_wrapper-0.1.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file unsplash_wrapper-0.1.0.tar.gz.

File metadata

  • Download URL: unsplash_wrapper-0.1.0.tar.gz
  • Upload date:
  • Size: 52.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.8

File hashes

Hashes for unsplash_wrapper-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7cd3e2f662491f7fcfdd2974a466b9060ff96567f8aa1298a4c354bc49664252
MD5 7cb371b68ba3948ce06d087717b9ec3b
BLAKE2b-256 67db1e1b771127c3f0273f5d053625744758d02b82cb2831827782b132bd2ff0

See more details on using hashes here.

File details

Details for the file unsplash_wrapper-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for unsplash_wrapper-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ddc17ee10237dd744e665fd81f80ca4c9bbdec428a32be9586b507abcd2e4324
MD5 0ce40bb534872d64a79d07bf7b57a9a0
BLAKE2b-256 6f34953c23408e9595238c2fb4c2a919e57a77fb17f152a6a6156c1fcddfed65

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page