Registry / web-framework / pywebpush

pywebpush

JSON →
library2.4.0pypypi✓ verified 25d ago

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.

pip install pywebpush
INSTALL
IMPORT
SIG · PYWEBPUSH
P
pywebpush
web-frameworkpythonv2.4.0
Install
6.3s avg
Import
747ms
Disk
48MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.4.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.782s · 48.3MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 6.3s · import 0.712s · 50MB
48MB installed
● package 48MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

webpush
from pywebpush import webpush
Convenience function for a single push notification send.
WebPusher
from pywebpush import WebPusher
Class for more granular control, especially for resending to the same recipient or encoding data separately.
WebPushException
from pywebpush import WebPushException
Exception class raised on push failures.

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.

import os import json from pywebpush import webpush, WebPushException # --- Configuration --- # # Get VAPID private key from environment variable for security VAPID_PRIVATE_KEY = os.environ.get('WEBPUSH_VAPID_PRIVATE_KEY', 'your-vapid-private-key-here') # Your email or a mailto: URL for VAPID identification VAPID_SENDER_INFO = os.environ.get('WEBPUSH_SENDER_INFO', 'mailto:admin@example.com') # Example PushSubscription object (obtained from the client-side) # In a real application, this would be retrieved from a database. subscription_info = { "endpoint": "https://fcm.googleapis.com/fcm/send/SOME_ENDPOINT_ID", "keys": { "auth": "SOME_AUTH_KEY", "p256dh": "SOME_P256DH_KEY" } } # The payload data to send message_data = { "title": "Hello from pywebpush!", "body": "Your notification arrived.", "icon": "/images/notification-icon.png" } try: # Define VAPID claims. The 'aud' (audience) must be the origin of the push service endpoint. # pywebpush attempts to guess 'aud' but it's best to be explicit. # 'exp' (expiration) is set to 12 hours by default if not provided. vapid_claims = { "sub": VAPID_SENDER_INFO, "aud": subscription_info['endpoint'].split('/fcm/send/')[0] # Extract origin for FCM } print("Attempting to send push notification...") response = webpush( subscription_info=subscription_info, data=json.dumps(message_data), # Data should be a JSON string for common use cases vapid_private_key=VAPID_PRIVATE_KEY, vapid_claims=vapid_claims ) print(f"Push notification sent successfully! Status: {response.status_code}") print(f"Response: {response.text}") except WebPushException as e: print(f"Failed to send push notification: {e}") print(f"Response body: {e.response_body}") # Handle specific errors, e.g., expired subscription, invalid VAPID keys except Exception as e: print(f"An unexpected error occurred: {e}") # Example of using WebPusher class for more control (e.g., encoding data separately) # try: # pusher = WebPusher(subscription_info) # encoded_data = pusher.encode(json.dumps(message_data)) # # You can now send encoded_data with custom HTTP client if needed # # Or use pusher.send() if you want pywebpush to handle HTTP request # # response = pusher.send(json.dumps(message_data), headers=headers_dict) # headers_dict would include VAPID auth # print("Data encoded successfully via WebPusher.") # except WebPushException as e: # print(f"Error encoding data: {e}")
Debug
Known issues
breakingIn version 2.0.0, the `Webpusher.encode()` method was changed to raise a `NoData` exception if no data is present, instead of returning `None`. This impacts scenarios where empty payloads were implicitly allowed or handled differently.
fix
Ensure that `Webpusher.encode()` is always called with data, or explicitly handle the `NoData` exception if empty payloads are expected.
affects: >=2.0.0
gotchaVAPID 'aud' claim is critical: Push services, especially FCM, require the `aud` claim in the VAPID token to explicitly match the origin of the push service endpoint (e.g., 'https://fcm.googleapis.com'). While `pywebpush` attempts to auto-fill this, explicitly setting it in `vapid_claims` is highly recommended to avoid `403 Forbidden` errors.
fix
When calling `webpush()` or `WebPusher.send()`, pass `vapid_claims={'sub': 'mailto:your@example.com', 'aud': 'https://your-push-service-origin.com'}`. Extract the origin from the `subscription_info['endpoint']`.
affects: All versions
deprecatedThe `aesgcm` content encoding is deprecated by RFC 8188. While pywebpush might still support it, the standard and default is `aes128gcm`. Not all user agents may decrypt `aesgcm` correctly.
fix
Always use or ensure `aes128gcm` content encoding. pywebpush defaults to this, but be aware if manually configuring content types.
affects: All versions
deprecatedGoogle Cloud Messaging (GCM) has been sunset by Google. Users should migrate to Firebase Cloud Messaging (FCM). This library does not directly support sending messages to FCM using an `gcm_key` for authentication, which was disabled in June 2024.
fix
Ensure your push subscriptions are for FCM endpoints and use VAPID authentication instead of deprecated GCM keys.
affects: All versions
gotchaVAPID 'exp' (expiration) claim: If not specified or set in the past, `pywebpush` will set it to 12 hours from now. However, invalid or expired JWTs (often due to clock skew or too long an expiration) can lead to `401` or `403` errors. A VAPID header can live for up to 24 hours.
fix
For robust applications, consider regenerating the VAPID token more frequently or explicitly setting a reasonable, shorter expiration (e.g., 5 minutes from `time.time()`) in `vapid_claims` if encountering authentication issues.
affects: All versions
Errors
Common errors & fixes
pywebpush.webpush_errors.RequestError: Push service returned error 401: Unauthorized
The VAPID keys (public or private) are incorrect, mismatched, or improperly formatted, leading to an authentication failure with the push service.
fix
Verify that your `vapid_public_key` and `vapid_private_key` are correctly generated, stored, and passed as base64 URL-safe strings, and ensure `vapid_claims` contains a valid `sub` (e.g., `mailto:your@email.com`).
pywebpush.webpush_errors.WebPushException: Payload too large
The size of the encrypted message payload exceeds the maximum limit (typically 4096 bytes) allowed by the push service provider.
fix
Reduce the content of the `message` sent to the push service, as larger payloads cannot be delivered via Web Push.
pywebpush.webpush_errors.RequestError: Push service returned error 400: Bad Request
The `vapid_claims` dictionary provided to `send_web_push` is missing required fields (like `sub`) or contains malformed values, causing the push service to reject the request.
fix
Ensure the `vapid_claims` dictionary includes a valid `sub` field (e.g., `{"sub": "mailto:your@email.com"}`) and that all values are correctly formatted.
ModuleNotFoundError: No module named 'webpush'
The user is attempting to import the library using `webpush`, but the correct package name for the installed library is `pywebpush`.
fix
Change the import statement from `import webpush` to `import pywebpush` or from `from webpush import send_web_push` to `from pywebpush import send_web_push`.
Upgrade
Version history
2.4.0latest on PyPI · released Aug 6, 2026
Audit
Dependencies
pythonrequiredRequires Python 3.10 or newer.
Agent activity
10 hits · last 30 days
node
8
OpenAI (training)
1
Resources
pywebpush — pip install pywebpush · libregistry