{"library":"pywebpush","title":"pywebpush","description":"pywebpush is a Python library for publishing WebPush notifications, handling the encryption and sending of messages to push services. It currently supports version 2.3.0 and is actively maintained with periodic releases.","language":"python","status":"active","last_verified":"Thu May 14","install":{"commands":["pip install pywebpush"],"cli":null},"imports":["from pywebpush import webpush","from pywebpush import WebPusher","from pywebpush import WebPushException"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import os\nimport json\nfrom pywebpush import webpush, WebPushException\n\n# --- Configuration --- #\n# Get VAPID private key from environment variable for security\nVAPID_PRIVATE_KEY = os.environ.get('WEBPUSH_VAPID_PRIVATE_KEY', 'your-vapid-private-key-here')\n# Your email or a mailto: URL for VAPID identification\nVAPID_SENDER_INFO = os.environ.get('WEBPUSH_SENDER_INFO', 'mailto:admin@example.com')\n\n# Example PushSubscription object (obtained from the client-side)\n# In a real application, this would be retrieved from a database.\nsubscription_info = {\n    \"endpoint\": \"https://fcm.googleapis.com/fcm/send/SOME_ENDPOINT_ID\",\n    \"keys\": {\n        \"auth\": \"SOME_AUTH_KEY\",\n        \"p256dh\": \"SOME_P256DH_KEY\"\n    }\n}\n\n# The payload data to send\nmessage_data = {\n    \"title\": \"Hello from pywebpush!\",\n    \"body\": \"Your notification arrived.\",\n    \"icon\": \"/images/notification-icon.png\"\n}\n\ntry:\n    # Define VAPID claims. The 'aud' (audience) must be the origin of the push service endpoint.\n    # pywebpush attempts to guess 'aud' but it's best to be explicit.\n    # 'exp' (expiration) is set to 12 hours by default if not provided.\n    vapid_claims = {\n        \"sub\": VAPID_SENDER_INFO,\n        \"aud\": subscription_info['endpoint'].split('/fcm/send/')[0] # Extract origin for FCM\n    }\n\n    print(\"Attempting to send push notification...\")\n    response = webpush(\n        subscription_info=subscription_info,\n        data=json.dumps(message_data), # Data should be a JSON string for common use cases\n        vapid_private_key=VAPID_PRIVATE_KEY,\n        vapid_claims=vapid_claims\n    )\n\n    print(f\"Push notification sent successfully! Status: {response.status_code}\")\n    print(f\"Response: {response.text}\")\n\nexcept WebPushException as e:\n    print(f\"Failed to send push notification: {e}\")\n    print(f\"Response body: {e.response_body}\")\n    # Handle specific errors, e.g., expired subscription, invalid VAPID keys\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\n\n# Example of using WebPusher class for more control (e.g., encoding data separately)\n# try:\n#     pusher = WebPusher(subscription_info)\n#     encoded_data = pusher.encode(json.dumps(message_data))\n#     # You can now send encoded_data with custom HTTP client if needed\n#     # Or use pusher.send() if you want pywebpush to handle HTTP request\n#     # response = pusher.send(json.dumps(message_data), headers=headers_dict) # headers_dict would include VAPID auth\n#     print(\"Data encoded successfully via WebPusher.\")\n# except WebPushException as e:\n#     print(f\"Error encoding data: {e}\")","lang":"python","description":"This quickstart demonstrates sending a WebPush notification using the `webpush` convenience function. It requires a `subscription_info` object (obtained from the client-side browser), a VAPID private key, and VAPID claims. The VAPID private key and sender info are typically loaded from environment variables for security. Data is sent as a JSON string. Error handling for `WebPushException` is included.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-14","installed_version":"2.1.2","pypi_latest":"2.3.0","is_stale":true,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":6.4,"avg_import_s":1.13,"wheel_type":"sdist"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.83,"mem_mb":16.8,"disk_size":"47.7M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.12,"mem_mb":16.7,"disk_size":"47.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":7,"import_time_s":0.59,"mem_mb":16.8,"disk_size":"50M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.61,"mem_mb":16.7,"disk_size":"50M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":1.11,"mem_mb":18.9,"disk_size":"51.8M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.64,"mem_mb":18.8,"disk_size":"51.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":5.7,"import_time_s":1.04,"mem_mb":18.9,"disk_size":"54M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.01,"mem_mb":18.8,"disk_size":"54M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":1.19,"mem_mb":18.7,"disk_size":"41.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":2.17,"mem_mb":18.6,"disk_size":"41.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":5.6,"import_time_s":1.21,"mem_mb":18.7,"disk_size":"44M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.27,"mem_mb":18.6,"disk_size":"44M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":1.28,"mem_mb":19.5,"disk_size":"40.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.55,"mem_mb":19.4,"disk_size":"40.9M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":5.5,"import_time_s":1.1,"mem_mb":19.5,"disk_size":"43M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.41,"mem_mb":19.4,"disk_size":"43M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.79,"mem_mb":16.8,"disk_size":"48.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":1.04,"mem_mb":16.7,"disk_size":"48.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":8.1,"import_time_s":0.74,"mem_mb":16.8,"disk_size":"51M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pywebpush","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.85,"mem_mb":16.7,"disk_size":"51M"}]}}