Skip to main content

async-firebase logo

Lightweight asynchronous Python client for Firebase Cloud Messaging (FCM)

PyPI download month PyPI version fury.io PyPI license PyPI pyversions CI Codacy coverage

  • Free software: MIT license
  • Requires: Python 3.10+

Features

  • Extremely lightweight and does not rely on firebase-admin which is hefty
  • Send push notifications to Android, iOS, and Web devices
  • Multicast push notifications (up to 500 targets per call)
  • Send to topics and topic conditions
  • TTL, priority, and collapse-key support
  • Dry-run mode for testing
  • Topic management (subscribe/unsubscribe devices)
  • Async context manager for proper resource cleanup

Installation

pip install async-firebase

Quick Start

import asyncio

from async_firebase import AsyncFirebaseClient, Message, AndroidConfig


async def main():
    async with AsyncFirebaseClient() as client:
        client.creds_from_service_account_file("secret-store/mobile-app-79225efac4bb.json")

        # or using a dictionary
        # client.creds_from_service_account_info({...})

        android_config = AndroidConfig.build(
            priority="high",
            ttl=2419200,
            collapse_key="push",
            title="Store Changes",
            body="Recent store changes",
            data={"discount": "15%", "key_1": "value_1"},
        )
        message = Message(android=android_config, token="device-token-here")
        response = await client.send(message)

        print(response.success, response.message_id)


if __name__ == "__main__":
    asyncio.run(main())

send() returns an FCMResponse with success (bool), message_id (str), and exception (on failure) attributes.

Message Types

FCM supports notification messages (displayed automatically by the system when the app is in the background), data messages (handled entirely by your app), and a combination of both. Use notification messages for user-visible alerts; use data messages for silent pushes, background syncs, or when your app needs full control over how content is processed.

See Set the message type in the official Firebase documentation for details.

Platform Configs

Build platform-specific configs using the .build() classmethod. The builders support both notification and data-only messages — simply omit notification/alert fields to produce a data-only payload.

Android

from async_firebase import AndroidConfig

android_config = AndroidConfig.build(
    priority="high",
    ttl=2419200,
    collapse_key="push",
    data={"discount": "15%", "key_1": "value_1"},
    title="Store Changes",
    body="Recent store changes",
)

To send a data-only message (no notification), simply omit all notification fields:

android_config = AndroidConfig.build(
    priority="high",
    ttl=2419200,
    collapse_key="push",
    data={"discount": "15%", "key_1": "value_1"},
)

New in v6.0: image, ticker, sticky, event_timestamp, local_only, notification_priority, vibrate_timings_millis, default_vibrate_timings, default_sound, light_settings, default_light_settings, fcm_options, direct_boot_ok, bandwidth_constrained_ok, restricted_satellite_ok.

iOS (APNs)

from async_firebase import APNSConfig

apns_config = APNSConfig.build(
    priority="normal",
    ttl=2419200,
    apns_topic="store-updated",
    collapse_key="push",
    title="Store Changes",
    alert="Recent store changes",
    badge=1,
    category="test-category",
    custom_data={"discount": "15%", "key_1": "value_1"},
)

To send a data-only APNS message, omit all alert fields:

apns_config = APNSConfig.build(
    priority="high",
    ttl=2419200,
    collapse_key="push",
    badge=0,
    category="test-category",
    content_available=True,
    custom_data={"key_1": "value_1"},
)

New in v6.0: subtitle, sound as CriticalSound, fcm_options, live_activity_token.

Web Push

from async_firebase import WebpushConfig

webpush_config = WebpushConfig.build(
    data={"discount": "15%"},
    title="Store Changes",
    body="Recent store changes",
    link="https://example.com/store",
)

Note: client.build_android_config(), client.build_apns_config(), and client.build_webpush_config() are deprecated. Use the .build() classmethods directly.

Multicast

Send notifications to up to 500 devices at once:

from async_firebase import AsyncFirebaseClient, MulticastMessage, AndroidConfig

async with AsyncFirebaseClient() as client:
    client.creds_from_service_account_info({...})

    android_config = AndroidConfig.build(priority="high", title="News", body="Breaking news!")

    multicast = MulticastMessage(
        android=android_config,
        fids=["fid_1", "fid_2", "fid_3"],
    )
    batch_response = await client.send_each_for_multicast(multicast)

    for resp in batch_response.responses:
        print(resp.success, resp.message_id)

send_each_for_multicast() returns an FCMBatchResponse containing individual FCMResponse objects for each target.

MulticastMessage accepts fids (Firebase installation IDs), tokens (deprecated), or both — up to 500 targets combined.

Topics

Sending to a topic

from async_firebase import AsyncFirebaseClient, Message, AndroidConfig

async with AsyncFirebaseClient() as client:
    client.creds_from_service_account_info({...})

    message = Message(
        android=AndroidConfig.build(priority="high", title="News", body="Update!"),
        topic="breaking-news",
    )
    response = await client.send(message)

A Message accepts exactly one of: fid, token, topic, or condition. token is deprecated in favor of fid (the Firebase installation ID of the target app instance).

Managing topic subscriptions

from async_firebase import AsyncFirebaseClient

async with AsyncFirebaseClient() as client:
    client.creds_from_service_account_info({...})

    # Subscribe
    response = await client.subscribe_devices_to_topic(
        device_tokens=["token_1", "token_2"],
        topic_name="breaking-news",
    )

    # Unsubscribe
    response = await client.unsubscribe_devices_from_topic(
        device_tokens=["token_1", "token_2"],
        topic_name="breaking-news",
    )

Advanced Usage

Dry-run mode

Validate messages without actually sending them:

response = await client.send(message, dry_run=True)

Dry-run is available on send(), send_each(), and send_each_for_multicast().

Direct dataclass construction

For full control, construct message dataclasses directly instead of using .build():

from datetime import datetime, timezone
from async_firebase.messages import APNSConfig, APNSPayload, ApsAlert, Aps, Message

apns_config = APNSConfig(
    headers={
        "apns-expiration": str(int(datetime.now(timezone.utc).timestamp()) + 7200),
        "apns-priority": "10",
        "apns-topic": "test-topic",
        "apns-collapse-id": "something",
    },
    payload=APNSPayload(
        aps=Aps(
            alert=ApsAlert(title="some-title", body="alert-message"),
            badge=0,
            sound="default",
            content_available=True,
            category="some-category",
            mutable_content=False,
            custom_data={
                "link": "https://link-to-somewhere.com",
                "ticket_id": "YXZ-655512",
            },
        )
    ),
)

message = Message(apns=apns_config, token="device-token-here")
response = await client.send(message)

Error handling

Send failures raise specific exceptions from async_firebase.errors:

from async_firebase.errors import (
    AsyncFirebaseError,
    UnregisteredError,
    QuotaExceededError,
    InvalidArgumentError,
)

try:
    response = await client.send(message)
except UnregisteredError:
    # Device token is no longer valid — remove it
    ...
except QuotaExceededError:
    # FCM rate limit hit — back off and retry
    ...
except AsyncFirebaseError as e:
    print(e.code, e.message)

Failed responses also populate FCMResponse.exception without raising, depending on the send method.

Changelog

See CHANGES.md for the full release history.

License

async-firebase is offered under the MIT license.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

async_firebase-6.2.0.tar.gz (84.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

async_firebase-6.2.0-py3-none-any.whl (29.3 kB view details)

Uploaded Python 3

File details

Details for the file async_firebase-6.2.0.tar.gz.

File metadata

  • Download URL: async_firebase-6.2.0.tar.gz
  • Upload date:
  • Size: 84.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.14 Linux/6.17.0-1018-azure

File hashes

Hashes for async_firebase-6.2.0.tar.gz
Algorithm Hash digest
SHA256 5d1ff568b5f1e2c43d9f8a46d471248cc9c8f3fb50310862fef2a8b1c007b29d
MD5 187da58a13a7725fcc52d33654e0254d
BLAKE2b-256 984afb1e79c630631e3e68c4f5a66f90e80fe1b8b76e8324681527e2325321d8

See more details on using hashes here.

File details

Details for the file async_firebase-6.2.0-py3-none-any.whl.

File metadata

  • Download URL: async_firebase-6.2.0-py3-none-any.whl
  • Upload date:
  • Size: 29.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.14 Linux/6.17.0-1018-azure

File hashes

Hashes for async_firebase-6.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2dcd0ad6a2e88c4bf17ba3b93f3568c808f901cae806c7df58c1355368f169a2
MD5 5d5af7e3bb174da752b5ae896e405322
BLAKE2b-256 e91201447744aee8a7fea09739f0ecb15074fa3228b9e4235d22af8059acced0

See more details on using hashes here.

Release history Release notifications | RSS feed

6.2.2

2 files

6.2.1

2 files

This release

6.2.0 This release

2 files

6.1.2

2 files

6.1.1

2 files

6.1.0

2 files

6.0.2

2 files

6.0.1

2 files

6.0.0

2 files

5.2.0

2 files

5.1.1

2 files

5.1.0

2 files

5.0.0

2 files

4.1.0

2 files

4.0.0

2 files

3.12.1

2 files

3.12.0

2 files

3.11.0

2 files

3.10.0

2 files

3.9.0

2 files

3.8.0

2 files

3.7.0

2 files

3.6.3

2 files

3.6.2

2 files

3.6.1

2 files

3.6.0

2 files

3.5.0

2 files

3.4.1

2 files

3.4.0

2 files

3.3.0

2 files

3.2.0

2 files

3.1.1

2 files

3.1.0

2 files

3.0.0

2 files

2.7.0

2 files

2.6.1

2 files

2.6.0

2 files

2.5.1

2 files

2.5.0

2 files

2.4.0

2 files

2.3.0

2 files

2.2.0

2 files

2.1.0

2 files

2.0.3

2 files

2.0.2

2 files

2.0.1

2 files

2.0.0

2 files

1.9.1

2 files

1.9.0

2 files

1.8.0

2 files

1.7.0

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.3.5

2 files

1.3.4

2 files

1.3.3

2 files

1.3.2

2 files

1.3.1

2 files

1.3.0

2 files

1.2.1

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

0.4.0

2 files

0.3.0

2 files

0.1.0

2 files

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