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_to_topic(
        device_tokens=["token_1", "token_2"],
        topic_name="breaking-news",
    )

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

    for error in response.errors:
        print(f"Token at index {error.index} failed: {error.reason}")

subscribe_to_topic() and unsubscribe_from_topic() use the FCM v1 API, which makes one request per device token (up to 1000 tokens per call). HTTP failures such as 401 responses, timeouts and connection errors are reported per token in response.errors. topic_name may include the /topics/ prefix.

subscribe_devices_to_topic() and unsubscribe_devices_from_topic() use the legacy Instance ID API. They behave as before but are deprecated.

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.

Metadata

Release files for async-firebase 6.3.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 async-firebase 6.3.0
File Size Uploaded
async_firebase-6.3.0.tar.gz 129.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for async-firebase 6.3.0
File Interpreter ABI Platform
async_firebase-6.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 161.3 kB

Release files / async_firebase-6.3.0.tar.gz

Download URL async_firebase-6.3.0.tar.gz
Size 129.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ab0de000b44cd0c1bb4526a66db94f116b7121bb6afce8192a646e0b704aaf5f
BLAKE2b-256 checksum
How to use checksums
256cf199241197728fa378fdc403fef00d9080f3bb6b0d72ae0b2d0b5d3fa6d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / async_firebase-6.3.0-py3-none-any.whl

Download URL async_firebase-6.3.0-py3-none-any.whl
Size 32.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
93a43e02a625d958c83972b5d2af99a07041a9dcbcab0936feddb9f34ed7d8b8
BLAKE2b-256 checksum
How to use checksums
28fe752ef13b026812690a030ea2ce47a9e9acc8bd03af5232d7ab5e6de7d106
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

6.3.0 This release

2 release files

6.2.2

2 release files

6.2.1

2 release files

6.2.0

2 release files

6.1.2

2 release files

6.1.1

2 release files

6.1.0

2 release files

6.0.2

2 release files

6.0.1

2 release files

6.0.0

2 release files

5.2.0

2 release files

5.1.1

2 release files

5.1.0

2 release files

5.0.0

2 release files

4.1.0

2 release files

4.0.0

2 release files

3.12.1

2 release files

3.12.0

2 release files

3.11.0

2 release files

3.10.0

2 release files

3.9.0

2 release files

3.8.0

2 release files

3.7.0

2 release files

3.6.3

2 release files

3.6.2

2 release files

3.6.1

2 release files

3.6.0

2 release files

3.5.0

2 release files

3.4.1

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.7.0

2 release files

2.6.1

2 release files

2.6.0

2 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.5

2 release files

1.3.4

2 release files

1.3.3

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.1.0

2 release 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