{"id":5744,"library":"aioapns","title":"aioapns: Asynchronous APNs Client","description":"aioapns is an efficient and asynchronous APNs (Apple Push Notification service) client library for Python, built on asyncio. It allows developers to send push notifications to iOS, macOS, watchOS, and tvOS devices. The current version is 4.0, and it generally follows a moderate release cadence, with major versions introducing significant changes.","status":"active","version":"4.0","language":"en","source_language":"en","source_url":"https://github.com/Fatal1ty/aioapns","tags":["async","apns","push-notifications","apple","ios","mac"],"install":[{"cmd":"pip install aioapns","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Required for HTTP/2 communication with APNs. Version 4.0.0 or newer is required.","package":"h2","optional":false}],"imports":[{"symbol":"APNs","correct":"from aioapns import APNs"},{"symbol":"NotificationRequest","correct":"from aioapns import NotificationRequest"}],"quickstart":{"code":"import asyncio\nimport os\nfrom aioapns import APNs, NotificationRequest\n\nasync def main():\n    # Ensure you have these environment variables set or replace with actual values\n    # APNS_KEY_CONTENT: The content of your .p8 private key file (NOT the path)\n    # APNS_KEY_ID: Your 10-character key ID from Apple Developer website\n    # APNS_TEAM_ID: Your 10-character Team ID from Apple Developer website\n    # APNS_TOPIC: Your app's bundle ID (e.g., com.example.app)\n    # APNS_DEVICE_TOKEN: A valid device token obtained from an iOS/macOS device\n\n    key_content = os.environ.get('APNS_KEY_CONTENT', '-----BEGIN PRIVATE KEY-----\\nYOUR_P8_KEY_CONTENT_HERE\\n-----END PRIVATE KEY-----')\n    key_id = os.environ.get('APNS_KEY_ID', 'YOUR_KEY_ID')\n    team_id = os.environ.get('APNS_TEAM_ID', 'YOUR_TEAM_ID')\n    topic = os.environ.get('APNS_TOPIC', 'com.example.app')\n    device_id = os.environ.get('APNS_DEVICE_TOKEN', 'your_device_token_here')\n\n    if 'YOUR_P8_KEY_CONTENT_HERE' in key_content or 'YOUR_KEY_ID' == key_id or 'YOUR_TEAM_ID' == team_id or 'com.example.app' == topic or 'your_device_token_here' == device_id:\n        print(\"Please set APNS_KEY_CONTENT, APNS_KEY_ID, APNS_TEAM_ID, APNS_TOPIC, and APNS_DEVICE_TOKEN environment variables or replace placeholders in the code.\")\n        return\n\n    try:\n        apns_client = APNs(\n            key=key_content,  # For v4.0+, this is the key content (string), not a path\n            key_id=key_id,\n            team_id=team_id,\n            topic=topic,\n            use_sandbox=True, # Set to False for production environment\n        )\n\n        request = NotificationRequest(\n            device_id=device_id,\n            message={\n                'aps': {\n                    'alert': 'Hello from aioapns!',\n                    'sound': 'default',\n                    'badge': 1\n                },\n                'custom_data': 'some_value'\n            }\n        )\n\n        response = await apns_client.send_notification(request)\n\n        if response.is_successful:\n            print(f\"Notification successfully sent to {device_id}!\")\n        else:\n            print(f\"Failed to send notification. Status: {response.status}, Reason: {response.reason}\")\n\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n\nif __name__ == '__main__':\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates how to initialize the APNs client and send a simple push notification using an asynchronous context. It requires your APNs authentication key content, key ID, team ID, app bundle ID, and a device token. Remember to use the `use_sandbox=False` for production environments."},"warnings":[{"fix":"If upgrading from v3.x, read your `.p8` key file into a string and pass the string content to the `key` argument instead of the file path. Example: `key=Path('key.p8').read_text()`","message":"In v4.0, the `key` argument for `APNs` and `APNsKeyConnectionPool` classes changed from expecting a file path to expecting the *content* of the .p8 private key file as a string. Passing a path will now cause errors.","severity":"breaking","affected_versions":"4.0.0+"},{"fix":"Upgrade your Python environment to 3.8 or newer to ensure compatibility.","message":"Support for Python 3.6 and 3.7 was dropped in v3.2. Attempting to use aioapns v3.2 or newer with these Python versions will result in compatibility issues or installation failures.","severity":"breaking","affected_versions":"3.2.0+"},{"fix":"Upgrade to v3.0 or later to benefit from deadlock fixes and improved stability.","message":"Earlier versions (prior to v3.0) had a known issue with deadlocks following timeouts. While fixed in v3.0, users on older versions might experience unresponsiveness under certain network conditions.","severity":"gotcha","affected_versions":"1.x - 2.x"},{"fix":"Ensure your environment's `h2` package meets or exceeds the required version, and resolve any dependency conflicts if other libraries require an older version (consider virtual environments).","message":"The `h2` library is a critical underlying dependency for HTTP/2 communication. While `aioapns` specifies `h2>=4.0.0`, conflicts with other libraries that might pin older `h2` versions can lead to unexpected behavior or runtime errors.","severity":"gotcha","affected_versions":"All versions requiring h2>=4.0.0"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}