pybirdbuddy
pybirdbuddy is an asynchronous Python client for the undocumented GraphQL
API behind the Bird Buddy smart bird feeder. Sign in with a Bird Buddy account
to read your feeders and their state, browse your collections and media, and
finish the "postcard" sightings the feeder captures.
It is an unofficial client for an undocumented API that can change without notice, and is not affiliated with or endorsed by Bird Buddy.
Installation
pip install pybirdbuddy
Python 3.10–3.14 is supported.
Usage
import asyncio
import pprint
from birdbuddy.client import BirdBuddy
bb = BirdBuddy("user@email.com", "Pa$$w0rd")
# Using coroutines with async/await:
async def async_test():
await bb.refresh()
pprint.pprint(bb.feeders)
# Without async/await, including from a top-level module:
result = asyncio.run(bb.refresh())
pprint.pprint(result)
pprint.pprint(bb.feeders)
Note: only password login is supported currently. Google and other SSOs are not supported. If you've already set up your Bird Buddy with SSO, one option could be to register a new account with a password, and then redeem an invite code to your Bird Buddy under the new account. Some fields will be missing (such as firmware versions and off-grid status).
The feeders property will be an array of feeders with the following fields:
fragment ListFeederFields on FeederForPrivate {
battery {
charging # Boolean
percentage # Int (93)
state # String (enum: "HIGH")
}
food {
state # String (enum: "LOW")
}
id # String (UUID)
name # String
signal {
state # String (enum: "HIGH")
value # Int (rssi: -41)
}
state # String (enum: "READY_TO_STREAM")
temperature {
value # Int
}
}
New postcards arrive in the feed. Identify a postcard's visitor without collecting it, or collect it into your account:
from birdbuddy.client import BirdBuddy
async def main():
bb = BirdBuddy("user@email.com", "Pa$$w0rd")
postcards = await bb.new_postcards()
postcard = postcards[0]
# Preview the recognized species and media, without collecting:
analysis = await bb.identify_postcard(postcard)
print([species.name for species in analysis.species])
# Collect it into your account. collect_postcard reanalyzes internally
# (idempotent), so calling identify_postcard beforehand is not required.
collected = await bb.collect_postcard(postcard)
print(collected.species)
Translations
API responses can return translated strings by setting the client's
language_code property. Language codes are parsed using
langcodes.
from birdbuddy.client import BirdBuddy
async def main():
bb = BirdBuddy("user@email.com", "Pa$$w0rd")
bb.language_code = "de"
collections = await bb.refresh_collections()
birds = [c.species.name for c in collections.values()]
print(birds)
Deprecations
Deprecated methods keep working and emit a DeprecationWarning, so upgrading
does not break existing callers. Prefer the replacement:
latest_collections()— deprecated in 0.0.22; userefresh_collections(). The old method referenced an undefined query and raisedAttributeErroron every call, so it never returned data. It now delegates torefresh_collections(), which returns the account's bird collections.reanalyze_postcard()— deprecated in 0.0.22; useidentify_postcard(), which returns aPostcardAnalysis(recognized species and media) instead of the raw payload.sighting_from_postcard(),finish_postcard(),sighting_choose_species(), andsighting_choose_mystery()— deprecated in 0.0.22; the report-token flow is superseded byidentify_postcard()andcollect_postcard().sighting_create()andsighting_create_check_progress()— deprecated in 0.0.22; the API removed the underlying mutations, so these raiseNotImplementedError.
Development
Install pyenv and the pinned interpreter, then use the Makefile — every target runs inside the project venv automatically:
pyenv install 3.10.20 # matches .python-version
make deps # create the venv and install the [dev] extra
make test # ruff + ruff format --check + markdownlint + pyright + pytest
make check # alias for `make test`
make format # auto-fix ruff issues and reformat
make schema # refresh schema.json from the live API
Alternatively, install the tooling into an existing environment with
pip install -e '.[dev]'.
Releasing
The package is published to PyPI. To cut a release:
- Bump
versioninpyproject.toml(if needed). make build— build the sdist and wheel intodist/.make publish— rebuild, runtwine check, then upload to PyPI.
make publish uses Twine, which reads credentials from ~/.pypirc or the
TWINE_USERNAME / TWINE_PASSWORD environment variables; use __token__ as
the username and a PyPI API token (the value includes its pypi- prefix) as
the password.
License
Released under the MIT No Attribution license (MIT-0).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pybirdbuddy-0.1.0.tar.gz.
File metadata
- Download URL: pybirdbuddy-0.1.0.tar.gz
- Upload date:
- Size: 47.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fd3918039d84aea6a9d6fee5f9f5d77bc6f15936a0e8c5d0eeb351f4d54a4c1
|
|
| MD5 |
d1365023e9417d94f5160f3e4f0ed4ad
|
|
| BLAKE2b-256 |
c670a82c95b3ee8626a8d52c32997bc50fe05c8cff540b3d9c3e2050c93c0cee
|
File details
Details for the file pybirdbuddy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pybirdbuddy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54c7b7288cdb0531337c7653c38e62e3291ecdc2ca68d7b9578d5e27a6eb5703
|
|
| MD5 |
52e2e579e0d3c9826992fbf2b3d23f89
|
|
| BLAKE2b-256 |
57db2245467417d2038b11e8ef19313738b2a3dfa3b7e7598fdd8f10995af922
|