Models

All API responses are parsed into typed Pydantic models. Fields are accessible as regular Python attributes.

Wallhaven models

class xanax.sources.wallhaven.models.Wallpaper(**data)[source]

Bases: BaseModel

Single wallpaper from Wallhaven.

id: str
url: str
short_url: str
views: int
favorites: int
source: str
purity: str
category: str
dimension_x: int
dimension_y: int
resolution: str
ratio: str
file_size: int
file_type: str
created_at: datetime
colors: list[str]
path: str
thumbs: Thumbnails
tags: list[Tag]
uploader: Uploader | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.SearchResult(**data)[source]

Bases: BaseModel

Search results with pagination metadata.

data: list[Wallpaper]
meta: PaginationMeta
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.PaginationMeta(**data)[source]

Bases: BaseModel

Pagination metadata for Wallhaven search results.

current_page: int
last_page: int
per_page: int
total: int
query: str | QueryInfo | None
seed: str | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.Tag(**data)[source]

Bases: BaseModel

Information about a tag.

id: int
name: str
alias: str | None
category_id: int | None
category: str | None
purity: str | None
created_at: datetime | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.Uploader(**data)[source]

Bases: BaseModel

Information about the wallpaper uploader.

username: str
group: str
avatar: Avatar | None
classmethod from_dict(data)[source]
Return type:

Uploader

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.Avatar(**data)[source]

Bases: BaseModel

User avatar at different sizes.

large: str | None
medium: str | None
small: str | None
tiny: str | None
classmethod from_dict(data)[source]
Return type:

Avatar | None

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.Thumbnails(**data)[source]

Bases: BaseModel

Thumbnail URLs at different sizes.

large: str
original: str
small: str
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.QueryInfo(**data)[source]

Bases: BaseModel

Information about a resolved search query.

id: int
tag: str
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.UserSettings(**data)[source]

Bases: BaseModel

User account settings.

thumb_size: str
per_page: str
purity: list[str]
categories: list[str]
resolutions: list[str]
aspect_ratios: list[str]
toplist_range: str
tag_blacklist: list[str]
user_blacklist: list[str]
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.Collection(**data)[source]

Bases: BaseModel

User collection information.

id: int
label: str
views: int
public: bool
count: int
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.wallhaven.models.CollectionListing(**data)[source]

Bases: BaseModel

Collection listing response (mirrors SearchResult structure).

data: list[Wallpaper]
meta: PaginationMeta
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.pagination.PaginationHelper(meta)[source]

Bases: object

Helper class for navigating paginated Wallhaven search results.

Wraps PaginationMeta and exposes clean properties and methods for driving pagination loops.

Example

results = client.search(params) helper = PaginationHelper(results.meta)

if helper.has_next:

next_params = params.with_page(helper.next_page_number()) next_results = client.search(next_params)

__init__(meta)[source]
property current_page: int

Current page number (1-indexed).

property last_page: int

Last available page number.

property per_page: int

Number of results per page.

property total: int

Total number of results across all pages.

property has_next: bool

Return True if there is a next page available.

property has_previous: bool

Return True if there is a previous page.

property seed: str | None

Seed value for random sorting (used for consistent pagination).

next_page_number()[source]

Return the next page number, or None if already on the last page.

Return type:

int | None

previous_page_number()[source]

Return the previous page number, or None if already on the first page.

Return type:

int | None


Unsplash models

class xanax.sources.unsplash.models.UnsplashPhoto(**data)[source]

Bases: BaseModel

A photo from Unsplash.

Fields with | None defaults correspond to data only present in full photo responses (from GET /photos/:id or GET /photos/random). Search results return abbreviated objects with these fields absent.

Example

photo = unsplash.photo(“abc123”) data = unsplash.download(photo)

id: str
created_at: datetime
updated_at: datetime | None
width: int
height: int
color: str | None
blur_hash: str | None
description: str | None
alt_description: str | None
urls: UnsplashPhotoUrls
user: UnsplashUser
downloads: int | None
public_domain: bool | None
exif: UnsplashExif | None
location: UnsplashLocation | None
tags: list[UnsplashTag]
property resolution: str

Formatted resolution string, e.g. '3840x2160'.

property aspect_ratio: float

Width-to-height ratio, rounded to two decimal places.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.unsplash.models.UnsplashSearchResult(**data)[source]

Bases: BaseModel

Paginated search results from GET /search/photos.

Example

result = unsplash.search(UnsplashSearchParams(query="mountains"))
print(result.total)         # total matching photos
print(result.total_pages)   # number of pages available
for photo in result.results:
    print(photo.id)
total: int
total_pages: int
results: list[UnsplashPhoto]
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.unsplash.models.UnsplashPhotoUrls(**data)[source]

Bases: BaseModel

Photo URLs at various resolutions provided by the Unsplash CDN.

raw: str
full: str
regular: str
small: str
thumb: str
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Bases: BaseModel

Hypermedia links associated with a photo.

self: str
html: str
download: str
download_location: str
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.unsplash.models.UnsplashUser(**data)[source]

Bases: BaseModel

Photographer who uploaded the photo.

id: str
username: str
name: str
first_name: str | None
last_name: str | None
bio: str | None
location: str | None
portfolio_url: str | None
instagram_username: str | None
twitter_username: str | None
total_collections: int
profile_image: UnsplashUserProfileImage | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].


Reddit models

class xanax.sources.reddit.models.RedditPost(**data)[source]

Bases: BaseModel

A single media post from Reddit.

Represents one image, video, or GIF found in a subreddit listing. Gallery posts are not returned directly — the client expands them into one RedditPost per image, populating gallery_index and gallery_id.

Example

post = reddit.post("abc123")
if post:
    data = reddit.download(post)
id: str
fullname: str
title: str
subreddit: str
author: str
score: int
url: str
media_type: MediaType
width: int | None
height: int | None
duration: int | None
video_url: str | None
is_nsfw: bool
created_utc: datetime
gallery_index: int | None
gallery_id: str | None
thumbnail_url: str | None
classmethod from_reddit_data(data)[source]

Build a RedditPost from a raw Reddit API post dict.

Detects the media type and extracts the appropriate URL and dimension fields. Returns None for post types that carry no downloadable media (text posts, external links without supported image domains, polls, etc.).

Media type detection order:

  1. is_self=True — text post, skip (return None).

  2. is_video=True and domain='v.redd.it' — VIDEO (or GIF when is_gif=True on the reddit_video object).

  3. is_gallery=True — IMAGE; url is left empty because the client calls _expand_gallery() to produce per-image posts.

  4. post_hint='image' or domain in ('i.redd.it', 'i.imgur.com') — IMAGE.

  5. Anything else — skip (return None).

Parameters:

data (dict[str, Any]) – Raw post data dict from data.children[n].data.

Return type:

RedditPost | None

Returns:

Parsed RedditPost, or None if the post has no supported media.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.reddit.models.RedditGalleryItem(**data)[source]

Bases: BaseModel

A single image extracted from a Reddit gallery post.

Reddit galleries store image metadata in media_metadata keyed by media_id. RedditGalleryItem holds the parsed fields for one such entry.

media_id: str
url: str
width: int | None
height: int | None
mime_type: str | None
caption: str | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class xanax.sources.reddit.models.RedditListing(**data)[source]

Bases: BaseModel

A paginated page of posts from a subreddit listing endpoint.

Example

listing = reddit.listing(RedditParams(subreddit="EarthPorn"))
for post in listing.posts:
    print(post.id, post.url)
if listing.after:
    next_listing = reddit.listing(params.with_after(listing.after))
posts: list[RedditPost]
after: str | None
before: str | None
dist: int
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].