Skip to main content

pybirdbuddy

Build Status Maintenance GitHub Release PyPI Version License

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; use refresh_collections(). The old method referenced an undefined query and raised AttributeError on every call, so it never returned data. It now delegates to refresh_collections(), which returns the account's bird collections.
  • reanalyze_postcard() — deprecated in 0.0.22; use identify_postcard(), which returns a PostcardAnalysis (recognized species and media) instead of the raw payload.
  • sighting_from_postcard(), finish_postcard(), sighting_choose_species(), and sighting_choose_mystery() — deprecated in 0.0.22; the report-token flow is superseded by identify_postcard() and collect_postcard().
  • sighting_create() and sighting_create_check_progress() — deprecated in 0.0.22; the API removed the underlying mutations, so these raise NotImplementedError.

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:

  1. Bump version in pyproject.toml (if needed).
  2. make build — build the sdist and wheel into dist/.
  3. make publish — rebuild, run twine 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).

Release files for pybirdbuddy 0.1.0

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

Source distribution (sdist)

Source distribution for pybirdbuddy 0.1.0
File Size Uploaded
pybirdbuddy-0.1.0.tar.gz 47.9 kB Details

Built distribution (wheel)

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

Total release size: 82.5 kB

Release files / pybirdbuddy-0.1.0.tar.gz

Download URL pybirdbuddy-0.1.0.tar.gz
Size 47.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3fd3918039d84aea6a9d6fee5f9f5d77bc6f15936a0e8c5d0eeb351f4d54a4c1
BLAKE2b-256 checksum
How to use checksums
c670a82c95b3ee8626a8d52c32997bc50fe05c8cff540b3d9c3e2050c93c0cee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / pybirdbuddy-0.1.0-py3-none-any.whl

Download URL pybirdbuddy-0.1.0-py3-none-any.whl
Size 34.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
54c7b7288cdb0531337c7653c38e62e3291ecdc2ca68d7b9578d5e27a6eb5703
BLAKE2b-256 checksum
How to use checksums
57db2245467417d2038b11e8ef19313738b2a3dfa3b7e7598fdd8f10995af922
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.21

2 release files

0.0.20

1 release file

0.0.19

1 release file

0.0.18

1 release file

0.0.17

1 release file

0.0.16

1 release file

0.0.15

1 release file

0.0.14

1 release file

0.0.13

1 release file

0.0.12

1 release file

0.0.11

1 release file

0.0.10

1 release file

0.0.9

1 release file

0.0.8

1 release file

0.0.7

1 release file

0.0.6

1 release file

0.0.5

1 release file

0.0.4

1 release file

0.0.3

1 release file

0.0.2

1 release file

0.0.1

1 release file

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