baark
A typed Python SDK for Bark push notifications. Matching
sync and async clients, connection pooling, rich notifications, and optional AES
encryption. Requires Python 3.13+; built on httpx2 and PyCryptodome.
Install
From PyPI:
uv add baark
Quick start
Copy your device key from Bark. A URL ending in the key also works.
from baark import Baark
with Baark("YOUR_DEVICE_KEY", group="backups") as client:
result = client.send(
"The backup finished.",
title="Backup",
logo="https://example.com/backup.png",
url="https://example.com/backups/latest",
)
print(result.ok)
Reuse the client for repeated sends; the context manager closes its connections.
result.ok confirms server acceptance, not delivery to the phone. For a single
send, use baark.send("Hello", device_key="YOUR_DEVICE_KEY").
Async
import asyncio
from baark import AsyncBaark
async def main() -> None:
async with AsyncBaark("YOUR_DEVICE_KEY") as client:
await client.send("Job finished", title="Build")
asyncio.run(main())
Both clients have the same options and operations; await async network calls.
The one-shot async helper is baark.async_send().
Notification options
Pass options to send(), store them in a Message, or set client defaults.
Per-call options override message fields, which override client defaults.
Pass None in a call to clear an inherited option.
| Purpose | Options |
|---|---|
| Content | body, title, subtitle, markdown |
| Media | icon / logo (aliases), image, sound |
| Attention | level, volume, badge, call |
| Interaction | url, action, copy, auto_copy |
| History | group, archive, ttl |
| Lifecycle | id, delete |
Use Python booleans for flags. Media URLs must be reachable by the phone. See message types for all options and Bark's field reference for device behavior.
Update and delete
with Baark("YOUR_DEVICE_KEY") as client:
client.send("Downloading…", id="download-42")
client.update("download-42", "Complete")
client.delete("download-42")
Updates replace the complete message using the same ID. They require Bark 1.5.2+ and bark-server 2.2.5+. Deletion removes the notification and its history entry; it requires Background App Refresh and may be delayed by iOS.
Encryption
Use GCM for new configurations. It encrypts the message and detects ciphertext tampering. CBC and ECB are available for compatibility with existing Bark settings.
import os
from baark import Baark, Encryption
settings = Encryption(os.environ["BAARK_ENCRYPTION_KEY"]) # GCM by default
with Baark("YOUR_DEVICE_KEY", encryption=settings) as client:
client.send("Private content", title="Private title")
Use the same key, algorithm, mode, and padding in Bark's Push Encryption settings. Keys are 16, 24, or 32 printable ASCII characters, selecting AES-128, AES-192, or AES-256. Key size and mode are separate choices: a longer key does not add tamper detection to CBC or ECB.
| Mode | Protection | IV / nonce in baark | Bark padding | Choose it for |
|---|---|---|---|---|
| GCM (default) | Encrypts and detects tampering | Fresh 12-character nonce per message | noPadding |
New setups |
| CBC | Encrypts; no tamper detection | Fresh 16-character IV by default | pkcs7 |
Existing CBC setups |
| ECB | Encrypts but reveals repeated blocks; no tamper detection | None | pkcs7 |
Legacy compatibility only |
An IV or nonce is a public value used alongside the key. Leave iv unset so
baark generates it for each GCM or CBC message; Bark reads it from the request.
Fixed GCM nonces are rejected because reuse breaks its security. Fixed CBC IVs
are supported for compatibility, but reuse leaks repeated message prefixes.
See PyCryptodome's GCM
and CBC/ECB
documentation for the underlying modes.
To create settings, run settings = Encryption.generate() once, save the key, and enter
settings.key, settings.algorithm, settings.mode, and settings.padding in
Bark. It defaults to AES-256-GCM. To import an encoded key, use
Encryption.from_key(value, encoding="hex") or encoding="base64"; enter the
decoded key in Bark. Hex and base64 are encodings, not encryption methods.
Encryption hides message fields, including titles and media URLs, from the Bark
server. Device routing, IVs, and id/delete controls remain visible. The key is
never sent. Without this option, HTTPS protects transport but the server can read
notification content.
Configuration and errors
Set server_url= for a custom server. Baark.from_env() and
AsyncBaark.from_env() read these optional settings from the process environment:
| Variable | Value |
|---|---|
BAARK_DEVICE_KEY |
Device key or URL ending in the key |
BAARK_SERVER_URL |
Custom server URL |
BAARK_ENCRYPTION_KEY |
Literal key matching Bark |
BAARK_ENCRYPTION_MODE |
GCM (default), CBC, or ECB |
BAARK_ENCRYPTION_IV |
Optional fixed CBC IV |
Ordinary constructors do not load these variables or config files. HTTP requests
default to a 10-second timeout, with redirects and retries disabled. Set
timeout=, auth=, or inject an httpx2.Client / AsyncClient with http_client=
for custom transport settings. Injected clients remain caller-owned; configure
authentication on them.
HTTP query defaults such as authentication tokens are preserved; notification and
routing fields come from baark's arguments and messages.
Send to multiple devices with client.send("Hello", device_keys=["KEY_A", "KEY_B"]).
Encrypted batches require all recipients to share encryption settings.
Partial failures raise BatchError; inspect error.response.deliveries for each
result. All SDK errors inherit from BaarkError. APIError exposes
status_code, code, and apns_reason; raw server_message is available
explicitly and may contain sensitive data.
For alternate endpoints, server utilities, registration, and URL building, see the client API. Also see response and message types, errors, and encryption helpers.
Alternatives
| Project | Useful when you want | Documented encryption support |
|---|---|---|
| baark | Reusable, typed sync and async Bark clients in Python | GCM, CBC, ECB |
| iskoldtbark | A Bark CLI with saved devices, recipient groups, and per-device keys | AES-256-GCM; AES-128/192/256-CBC |
| bark-python | A small client with replaceable encryption strategies | Built-in CBC and ECB; custom strategies |
| Apprise | One library or CLI for Bark and other notification services | Bark AES-GCM |
For simple scripts, Bark's HTTP API also works directly with curl or your existing HTTP client.
Development
Install uv, just, and
actionlint, then run uv sync --locked.
Windows development also needs Bash, as provided by Git for Windows.
Test with your phone
Copy .env.example with cp -n .env.example .env, then edit .env with your
device key and optional encryption settings. Leave unused settings commented out.
uv run python scripts/e2e.py --list-cases
uv run --env-file .env python scripts/e2e.py --client sync --case logo image markdown
These selected cases send three real notifications. Check the phone, then repeat
with the same client and cases plus --action update or --action delete.
--case all covers nine cases; the default client selection, both, doubles
the count. Use --help for media URL overrides and other options.
Offline checks
just check
just build
just test-wheel
The test suite uses mock HTTP transports and encryption vectors. Coverage checks
enforce the threshold in pyproject.toml. CI tests the built wheel on Python 3.13
and 3.14 across Linux, macOS, and Windows.
License
MIT.
Metadata
Release files for baark 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| baark-0.1.0.tar.gz | 84.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| baark-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 111.0 kB
Release files / baark-0.1.0.tar.gz
| Download URL | baark-0.1.0.tar.gz |
|---|---|
| Size | 84.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc5ee0c84ddb991a022648a5bfa7ae2d278c5a7e06b2b391a4b34ecd07c744db
|
|
BLAKE2b-256 checksum How to use checksums |
dc36e6d4e00f4757fcad6d9873b1710cd9eecbc70a315f1b90ee76ab17210b7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / baark-0.1.0-py3-none-any.whl
| Download URL | baark-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9fb161c798458fc216de7bff0db9bdb88f236fd3ef40f4dfb3d092ad2ad9ab08
|
|
BLAKE2b-256 checksum How to use checksums |
ccc2ee56d815ade622f2f81692a2a3d847ae7bca037fa35ea503b77609e805b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logSecurity for baark 0.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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for baark-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logA 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.