Supabase Realtime Python Client
The `realtime` library is the official Python client for Supabase Realtime, offering capabilities for real-time communication. It allows applications to send and receive ephemeral messages via Broadcast, track and synchronize shared state with Presence, and listen for database changes using Postgres Change Data Capture (CDC). The current version is 2.28.3, and it receives frequent updates as part of the broader Supabase ecosystem.
Warnings
- gotcha The `REALTIME_URL` format is crucial. For local development, it's typically `ws://localhost:4000/websocket`. For a deployed Supabase project, use `wss://<project_ref>.supabase.co/realtime/v1`. Using the incorrect URL can lead to connection failures.
- breaking The protocol for `postgres_changes` has shifted from using the key 'events' to 'event' in the payload. Older clients expecting 'events' will fail to process real-time database changes correctly.
- gotcha Realtime connections can experience timeouts or failed subscriptions, often due to network instability, incorrect API keys, or server-side issues. Common errors include 'keepalive ping timeout' or 'join push timeout'.
- deprecated Python 3.8 support might be deprecated in future releases, following the general trend of the Supabase Python ecosystem. The library currently requires Python 3.9+.
- gotcha The `API_KEY` used for connecting to the Realtime server, especially for private channels, must be a JWT that includes `exp` (expiration) and `role` (database role) claims. An invalid or expired JWT will result in authorization failures.
Install
-
pip install realtime
Imports
- AsyncRealtimeClient
from realtime import AsyncRealtimeClient
- RealtimeSubscribeStates
from realtime import RealtimeSubscribeStates
Quickstart
import asyncio
import os
from typing import Optional
from realtime import AsyncRealtimeClient, RealtimeSubscribeStates
async def main():
REALTIME_URL = os.environ.get('REALTIME_URL', 'ws://localhost:4000/websocket')
API_KEY = os.environ.get('SUPABASE_ANON_KEY', 'YOUR_SUPABASE_ANON_KEY') # Or your service role key
print(f"Connecting to {REALTIME_URL} with API Key: {API_KEY[:5]}...")
socket = AsyncRealtimeClient(REALTIME_URL, API_KEY)
channel = socket.channel("my_test_channel")
def _on_subscribe(status: RealtimeSubscribeStates, err: Optional[Exception]):
if status == RealtimeSubscribeStates.SUBSCRIBED:
print("Connected to channel!")
elif status == RealtimeSubscribeStates.CHANNEL_ERROR:
print(f"Error subscribing to channel: {err}")
elif status == RealtimeSubscribeStates.TIMED_OUT:
print("Subscription timed out.")
elif status == RealtimeSubscribeStates.CLOSED:
print("Channel unexpectedly closed.")
# Listen for database changes (example: all changes in 'public' schema)
channel.on_postgres_changes(
"*",
schema="public",
callback=lambda payload: print("Database change received:", payload)
)
# Listen for broadcast messages
channel.on_broadcast("my-event", lambda payload: print("Broadcast received:", payload))
await channel.subscribe(_on_subscribe)
await asyncio.sleep(60) # Keep the client alive for 60 seconds
await socket.disconnect()
if __name__ == "__main__":
# Set these environment variables or replace placeholders for a live connection
# os.environ['REALTIME_URL'] = 'wss://<project_ref>.supabase.co/realtime/v1'
# os.environ['SUPABASE_ANON_KEY'] = 'eyJ...'
asyncio.run(main())