{"library":"pyapns-client","title":"pyapns-client: Apple Push Notifications (HTTP/2)","description":"pyapns-client is a Python library designed for sending Apple Push Notifications (APNs) to iOS, macOS, and Safari using the modern HTTP/2 Push provider API. It focuses on simplicity, flexibility, and speed, leveraging token-based authentication for enhanced security and avoiding certificate renewal hassles. The current version is 2.0.6, with a more recent async-enabled version (pyapns-client3) also available. This library is actively maintained, with the latest update for the 2.x series in June 2022.","language":"python","status":"active","last_verified":"Fri May 15","install":{"commands":["pip install pyapns-client"],"cli":{"name":"pyapns-client","version":"sh: 1: pyapns-client: not found"}},"imports":["from pyapns_client import APNSClient","from pyapns_client import IOSPayloadAlert","from pyapns_client import IOSPayload","from pyapns_client import IOSNotification","from pyapns_client import APNSDeviceException","from pyapns_client import APNSServerException","from pyapns_client import APNSProgrammingException","from pyapns_client import UnregisteredException"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import os\nfrom pyapns_client import APNSClient, IOSPayloadAlert, IOSPayload, IOSNotification, APNSDeviceException, APNSServerException, APNSProgrammingException, UnregisteredException\n\n# --- Environment Variables (Replace with your actual values or secure fetching) ---\n# APNS_MODE: APNSClient.MODE_DEV or APNSClient.MODE_PROD\n# APNS_AUTH_KEY_PATH: Path to your .p8 authentication key file\n# APNS_AUTH_KEY_ID: Your 10-character Key ID from Apple Developer portal\n# APNS_TEAM_ID: Your 10-character Team ID from Apple Developer portal\n# APNS_ROOT_CERT_PATH: Path to Apple's root certificate (e.g., AppleWWDRCA.pem or AAACertificateServices.pem)\n#                      Can be None if included in your system's trust store or not strictly required for token-based auth.\n\nAPNS_MODE = os.environ.get('APNS_MODE', APNSClient.MODE_DEV) # Use MODE_PROD for production\nAPNS_AUTH_KEY_PATH = os.environ.get('APNS_AUTH_KEY_PATH', 'path/to/AuthKey_YOURKEYID.p8')\nAPNS_AUTH_KEY_ID = os.environ.get('APNS_AUTH_KEY_ID', 'YOURKEYID')\nAPNS_TEAM_ID = os.environ.get('APNS_TEAM_ID', 'YOURTEAMID')\nAPNS_ROOT_CERT_PATH = os.environ.get('APNS_ROOT_CERT_PATH', None) # Or 'path/to/AAACertificateServices.pem'\n\ndevice_token = os.environ.get('DEVICE_TOKEN', 'a_sample_device_token_hex_string')\nAPP_BUNDLE_ID = os.environ.get('APP_BUNDLE_ID', 'com.example.yourapp')\n\nif APNS_ROOT_CERT_PATH and not os.path.exists(APNS_ROOT_CERT_PATH):\n    print(f\"Warning: APNS_ROOT_CERT_PATH '{APNS_ROOT_CERT_PATH}' not found. Set it correctly or None.\")\n\nif not os.path.exists(APNS_AUTH_KEY_PATH):\n    print(f\"Error: APNS_AUTH_KEY_PATH '{APNS_AUTH_KEY_PATH}' not found. Please provide a valid path to your .p8 key.\")\n    exit(1)\n\ntry:\n    # Initialize the client using token-based authentication\n    client = APNSClient(\n        mode=APNS_MODE,\n        auth_key_path=APNS_AUTH_KEY_PATH,\n        auth_key_id=APNS_AUTH_KEY_ID,\n        team_id=APNS_TEAM_ID,\n        root_cert_path=APNS_ROOT_CERT_PATH # Optional, depends on your trust store setup\n    )\n\n    # Create the notification payload\n    alert = IOSPayloadAlert(title='Hello from pyapns-client!', subtitle='New Message', body='This is a test push notification.')\n    payload = IOSPayload(alert=alert, badge=1, sound='default')\n\n    # Create the notification object\n    notification = IOSNotification(payload=payload, topic=APP_BUNDLE_ID)\n\n    print(f\"Attempting to push notification to device: {device_token}\")\n    # Send the notification\n    client.push(notification=notification, device_token=device_token)\n    print(\"Notification sent successfully!\")\n\nexcept UnregisteredException as e:\n    print(f\"Device is unregistered: {e.device_token}. Remove from DB. Timestamp: {e.timestamp_datetime}\")\nexcept APNSDeviceException as e:\n    print(f\"Device error for {e.device_token}: {e.reason}. Flag device as invalid.\")\nexcept APNSServerException as e:\n    print(f\"APNs server error: {e.reason}. Try again later.\")\nexcept APNSProgrammingException as e:\n    print(f\"Programming error: {e.reason}. Check your code and APNs settings.\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\n","lang":"python","description":"This quickstart demonstrates how to send a basic push notification using token-based authentication with `pyapns-client`. It leverages environment variables for sensitive credentials and includes essential error handling for common APNs responses. Ensure you replace placeholder values with your actual Apple Developer details and a valid device token. The `topic` parameter must match your application's bundle ID.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-15","installed_version":"2.0.6","pypi_latest":"2.0.6","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":3.4,"avg_import_s":0.27,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.24,"mem_mb":8.5,"disk_size":"42.6M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.5,"import_time_s":0.17,"mem_mb":8.5,"disk_size":"43M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.35,"mem_mb":9.4,"disk_size":"45.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.7,"import_time_s":0.31,"mem_mb":9.4,"disk_size":"46M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.31,"mem_mb":9.2,"disk_size":"36.9M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3,"import_time_s":0.31,"mem_mb":9.2,"disk_size":"37M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.28,"mem_mb":9.6,"disk_size":"36.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.9,"import_time_s":0.28,"mem_mb":9.6,"disk_size":"37M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.23,"mem_mb":8.7,"disk_size":"42.4M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pyapns-client","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":4,"import_time_s":0.23,"mem_mb":8.7,"disk_size":"43M"}]}}