Skip to main content
Loss of provenance

A previous release had provenance metadata, but this release does not. View details.

Pychive

Unofficial Python wrapper for the Pawchive API. This project is not affiliated with, endorsed by, or associated with Pawchive.

Pychive provides a clean, typed, object-oriented interface to Pawchive's REST API — covering creators, posts, comments, announcements, fancards, post flagging, favorites, file-hash search, and app version info.

Documentation

Full documentation — installation, quick start, authentication, configuration, API reference, models, exceptions, error handling, pagination, cookbook, and changelog — lives in docs/index.md.

Installation

From PyPI

pip install pychive

From source (local build)

git clone https://gitlab.com/forgiving/pychive.git
cd Pychive
pip install .
Optional: use a virtual environment
git clone https://gitlab.com/forgiving/pychive.git
cd Pychive

python3 -m venv .venv
source .venv/bin/activate      # Linux / macOS
# .venv\Scripts\activate       # Windows

pip install .

Verify the install

python -c "import pychive; print(pychive.__version__)"

(Optional) Install dev tooling

pip install -e ".[dev]"

This adds pytest, responses, ruff, and mypy for testing/linting.


Quick start

import os
from pychive import Pawchive, AuthenticationError, NotFoundError

# Log in with username / password — Pychive captures the session cookie.
# Or pass a session cookie directly: Pawchive("your_session_value")
# Or run anonymously for public endpoints: Pawchive()
client = Pawchive(
    username=os.environ["PAWCHIVE_USERNAME"],
    password=os.environ["PAWCHIVE_PASSWORD"],
)

# Public endpoints (no auth needed)
creators = client.creators.list_all()
for c in creators:
    print(c.name, c.service, c.url)

# Recent posts across all creators (paginated)
posts = client.posts.list_recent(limit=50, offset=0)
for p in posts:
    print(p.title, p.published_at)

# Posts from a specific creator
fanbox_posts = client.posts.list_from_creator("fanbox", "12345", limit=20)

# A specific post + its revisions and comments
post = client.posts.get("fanbox", "12345", "67890")
revisions = client.posts.list_revisions("fanbox", "12345", "67890")
comments = client.comments.list("fanbox", "12345", "67890")

# Creator profile / links / tags / announcements / fancards
profile = client.creators.get_profile("fanbox", "12345")
links = client.creators.get_links("fanbox", "12345")
tags = client.creators.get_tags("fanbox", "12345")
announcements = client.creators.get_announcements("fanbox", "12345")
fancards = client.creators.get_fancards("fanbox", "12345")  # fanbox only

# Authorized endpoints (require valid credentials)
try:
    favs = client.favorites.list()
    client.favorites.add_post("fanbox", "12345", "67890")
    client.favorites.add_creator("fanbox", "12345")
    client.flags.flag("fanbox", "12345", "67890")
    flag_status = client.flags.get_status("fanbox", "12345", "67890")
except AuthenticationError:
    print("Session is invalid or expired.")

# File search by hash + app version
result = client.search.lookup_hash("abcdef1234567890")
version = client.misc.app_version()

client.close()

Authentication

Pychive supports three auth modes:

  1. Username / password (recommended) — Pychive logs in to pawchive.pw/account/login and captures the session cookie:
    client = Pawchive(username="your_username", password="your_password")
    
  2. Session cookie — pass the session cookie value directly:
    client = Pawchive("your_session_value")
    client = Pawchive("session=your_session_value")  # prefix optional
    
  3. Anonymous — no credentials; public endpoints only:
    client = Pawchive()
    

You can load credentials from environment variables:

import os
from pychive import Pawchive

client = Pawchive(
    username=os.environ["PAWCHIVE_USERNAME"],
    password=os.environ["PAWCHIVE_PASSWORD"],
)
export PAWCHIVE_USERNAME="your_username"
export PAWCHIVE_PASSWORD="your_password"

API surface

The Pawchive client exposes endpoint groups as properties:

Property Class Single-id methods Multi-id (*_many) methods Auth?
client.creators CreatorsEndpoint list_all(), get_profile(s,cid), get_links(s,cid), get_tags(s,cid), get_announcements(s,cid), get_fancards(s,cid) get_profile_many(s,cids), get_links_many(s,cids), get_tags_many(s,cids), get_announcements_many(s,cids), get_fancards_many(cids) No (fancards: fanbox only)
client.posts PostsEndpoint list_recent(l,o), list_from_creator(s,cid,l,o), get(s,cid,pid), list_revisions(s,cid,pid) list_from_creator_many(s,cids,l,o), get_many(s,cid,pids), list_revisions_many(s,cid,pids) No
client.comments CommentsEndpoint list(s,cid,pid) list_many(s,cid,pids) No
client.flags FlagsEndpoint flag(s,cid,pid), get_status(s,cid,pid) flag_many(s,cid,pids), get_status_many(s,cid,pids) Yes
client.favorites FavoritesEndpoint list(), add_post(s,cid,pid), remove_post(s,cid,pid), add_creator(s,cid), remove_creator(s,cid) add_post_many(s,cid,pids), remove_post_many(s,cid,pids), add_creator_many(s,cids), remove_creator_many(s,cids) Yes
client.search SearchEndpoint lookup_hash(hash) — No
client.misc MiscEndpoint app_version() — No

Multi-id methods accept a string or iterable of ids, return a dict keyed by id, and accept an optional delay keyword to throttle between requests. A bare string is treated as a single id (not character-split).

Constructor options

Pawchive(
    session=None,            # str | None: session cookie value
    *,
    username=None,           # str | None: Pawchive username
    password=None,           # str | None: Pawchive password
    login_url="https://pawchive.pw/account/login",
    base_url="https://pawchive.pw/api/v1",
    timeout=30,              # per-request timeout (seconds)
    max_retries=3,           # retries on 429 / 5xx
    backoff_base=0.5,        # exponential backoff base (seconds)
)

Error handling

All errors inherit from pychive.PawchiveError. Catch the base class or a specific subclass:

Exception When raised
PawchiveError Base class for all wrapper errors
AuthenticationError HTTP 401 (invalid/missing session)
NotFoundError HTTP 404
RateLimitError HTTP 429 after retries exhausted
ClientError Other HTTP 4xx
ServerError HTTP 5xx after retries exhausted
ValidationError Invalid arguments passed to a method
ConnectionError Network/timeout failures

Each HTTP exception carries .status_code and .response (the original requests.Response). RateLimitError also exposes .retry_after.

import os
from pychive import Pawchive, RateLimitError, AuthenticationError, NotFoundError

client = Pawchive(
    username=os.environ["PAWCHIVE_USERNAME"],
    password=os.environ["PAWCHIVE_PASSWORD"],
)
try:
    post = client.posts.get("fanbox", "12345", "67890")
except NotFoundError:
    print("Post not found.")
except AuthenticationError:
    print("Session expired.")
except RateLimitError as e:
    print(f"Rate limited; server suggested waiting {e.retry_after}s")
finally:
    client.close()

Retry behavior: the client automatically retries 429, 502, 503, and 504 responses up to max_retries times with exponential backoff. It honors the Retry-After header when present (capped at 60s).


Project layout

Pychive/
├── pyproject.toml          # packaging + tool config
├── README.md
├── AGENTS.md               # compact guide for AI coding sessions
├── docs/                   # full documentation (Markdown)
│   ├── index.md            # entry point + table of contents
│   ├── installation.md
│   ├── quickstart.md
│   ├── authentication.md
│   ├── configuration.md
│   ├── api-reference.md    # every endpoint, method, return type
│   ├── models.md           # every dataclass and its fields
│   ├── exceptions.md
│   ├── error-handling.md
│   ├── pagination.md
│   ├── cookbook.md         # complete examples
│   └── changelog.md
├── tests/                  # pytest test suite (responses for HTTP mocking)
│   ├── conftest.py         # shared fixtures (client with max_retries=0)
│   ├── test_session_parsing.py
│   ├── test_models.py
│   ├── test_validation.py
│   ├── test_endpoints.py
│   ├── test_error_handling.py
│   └── test_client.py
└── src/
    └── pychive/
        ├── __init__.py     # public exports (Pawchive, models, exceptions)
        ├── client.py       # Pawchive — main client class
        ├── http.py         # HttpClient — transport, auth, retry/backoff
        ├── exceptions.py   # exception hierarchy
        ├── models.py       # frozen dataclasses for API responses
        ├── py.typed        # PEP 561 marker (typed package)
        └── endpoints/
            ├── __init__.py
            ├── base.py        # BaseEndpoint
            ├── creators.py    # list_all, profile, links, tags, announcements, fancards
            ├── posts.py       # recent, creator posts, specific post, revisions
            ├── comments.py    # post comments
            ├── flags.py       # flag / flag status
            ├── favorites.py   # list / add / remove posts & creators
            ├── search.py      # hash lookup
            └── misc.py        # app version

Development

pip install -e ".[dev]"

# lint
ruff check src
# type-check
mypy src
# tests
pytest

License

MIT

Metadata

Release files for pychive 1.1.0

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

Loss of provenance

These files do not have provenance metadata, despite files in a prior release including this data.

We recommend further investigation before installing these files. View details.

Source distribution (sdist)

Source distribution for pychive 1.1.0
File Size Uploaded Provenance
pychive-1.1.0.tar.gz 29.6 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 54.3 kB

Release files / pychive-1.1.0.tar.gz

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL pychive-1.1.0.tar.gz
Size 29.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b8bc0441264e1f00d40455114953ae32feae3f46d2cebf68687cf5c572d3474a
BLAKE2b-256 checksum
How to use checksums
886a5a23d9d1341a52d2f28cd3aeef4e5171e459358e2bc03071a0cb7e3b96ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / pychive-1.1.0-py3-none-any.whl

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL pychive-1.1.0-py3-none-any.whl
Size 24.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
911e6c20b91add50cb33230ebbba85223aaaeba0d43c07f12683201cb2373f5f
BLAKE2b-256 checksum
How to use checksums
d75978f9644a48dda38f49b7e07529fde5cd15af7e339f7d6df57fadf222a2ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.14.7

Security for pychive 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Loss of provenance

A previous release of these files had provenance metadata, but this release does not.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Release comparison

  • Removed 1.0.0 2 files With provenance
  • Added 1.1.0 2 files Without provenance

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files Loss of provenance

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