---
source_url: https://www.pubnub.com/docs/sdks/python/api-reference/publish-and-subscribe
title: Publish/Subscribe API for Python SDK
updated_at: 2026-05-21T15:47:26.688Z
sdk_name: PubNub Python SDK
sdk_version: 10.6.3
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Publish/Subscribe API for Python SDK

PubNub Python SDK, use the latest version: 10.6.3

Install:

```bash
pip install pubnub@10.6.3
```

PubNub delivers messages worldwide in less than 30 ms. Send a message to one recipient or broadcast to thousands of subscribers.

For higher-level conceptual details on publishing and subscribing, refer to [Connection Management](https://www.pubnub.com/docs/general/setup/connection-management) and to [Publish Messages](https://www.pubnub.com/docs/general/messages/publish).

:::note Request execution and return values
You can decide whether to perform the Python SDK operations synchronously or asynchronously.
* .sync() returns an Envelope object, which has two fields: Envelope.result, whose type differs for each API, and Envelope.status of type PnStatus. 1pubnub.publish() \2 .channel("myChannel") \3 .message("Hello from PubNub Python SDK") \4 .sync()
* .pn_async(callback) returns None and passes the values of Envelope.result and Envelope.status to a callback you must define beforehand. 1def my_callback_function(result, status):2 print(f'TT: {result.timetoken}, status: {status.category.name}')3 4pubnub.publish() \5 .channel("myChannel") \6 .message("Hello from PubNub Python SDK") \7 .pn_async(my_callback_function)
:::

## Publish

`publish()` sends a message to all channel subscribers. PubNub replicates the message across its points of presence and delivers it to all subscribed clients on that channel.

:::warning ObjectNode
The new Jackson parser does not recognize JSONObject. Use ObjectNode instead.
:::

###### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/python/api-reference/configuration#configuration) with the `publishKey`.
* You don't have to be subscribed to a channel to publish to it.
* You cannot publish to multiple channels simultaneously.

###### Security

Secure messages with Transport Layer Security (TLS) or Secure Sockets Layer (SSL) by setting `ssl` to `true` during [initialization](https://www.pubnub.com/docs/sdks/python/api-reference/configuration). You can also [encrypt](https://www.pubnub.com/docs/sdks/python/api-reference/configuration#crypto_module) messages.

###### Message data

The message can contain any JavaScript Object Notation (JSON)-serializable data (objects, arrays, integers, strings). Avoid special classes or functions. Strings can include any UTF‑8 characters.

:::warning Don't JSON serialize
You should not JSON serialize the `message` and `meta` parameters when sending signals, messages, or files as the serialization is automatic. Pass the full object as the message/meta payload and let PubNub handle everything.
:::

###### Size

The maximum message size is 32 KiB. This includes the escaped character count and the channel name. Aim for under 1,800 bytes for optimal performance.

If your message exceeds the limit, you'll receive a `Message Too Large` error. To learn more or calculate payload size, see [Message size limits](https://www.pubnub.com/docs/general/messages/publish#message-size-limit).

###### Publish rate

You can publish as fast as bandwidth allows. There is a [soft throughput limit](https://www.pubnub.com/docs/general/setup/limits) because messages may drop if subscribers can't keep up.

For example, publishing 200 messages at once may cause the first 100 to drop if a subscriber hasn't received any yet. The in-memory queue stores only 100 messages.

###### Custom message type

You can optionally provide the `custom_message_type` parameter to add your business-specific label or category to the message, for example `text`, `action`, or `poll`.

###### Best practices

* Publish to a channel serially (not concurrently).
* Verify a success return code (for example, `[1,"Sent","136074940..."]`).
* Publish the next message only after a success return code.
* On failure (`[0,"blah","<timetoken>"]`), retry.
* Keep the in-memory queue under 100 messages to avoid drops.
* Throttle bursts to meet latency needs (for example, no more than 5 messages per second).

### Method(s)

To `Publish a message` you can use the following method(s) in the Python SDK:

```python
pubnub.publish() \
    .channel(String) \
    .message(Object) \
    .custom_message_type(String) \
    .should_store(Boolean) \
    .meta(Dictionary) \
    .use_post(Boolean)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | Destination of `message` (channel ID). |
| message | Object | Yes |  | The payload. |
| custom_message_type | String | Optional |  | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |
| should_store | Boolean | Optional | `account default` | Store in history |
| meta | Object | Optional | `None` | Meta data object which can be used with the filtering ability. |

### Sample code

#### Publish a message to a channel

:::tip Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
:::

###### Builder Pattern

```python
import os
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.exceptions import PubNubException

def publish_message(pubnub: PubNub):
    try:
        envelope = pubnub.publish() \
            .channel("my_channel") \
            .message({
                'name': 'Alex',
                'online': True
            }) \
            .custom_message_type("text-message") \
            .sync()
        print("Publish timetoken: %d" % envelope.result.timetoken)
    except PubNubException as e:
        print(f"Error: {e}")

def main():
    # Configuration for PubNub instance
    pn_config = PNConfiguration()
    pn_config.subscribe_key = os.getenv('SUBSCRIBE_KEY', 'demo')
    pn_config.publish_key = os.getenv('PUBLISH_KEY', 'demo')
    pn_config.user_id = os.getenv('USER_ID', 'my_custom_user_id')

    # Initialize PubNub client
    pubnub = PubNub(pn_config)

    # Publish message
    publish_message(pubnub)

if __name__ == "__main__":
    main()
```

###### Named Arguments

```python
import os
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.exceptions import PubNubException

def publish_message(pubnub: PubNub):
    try:
        envelope = pubnub.publish(
            channel="my_channel",
            message={
                'name': 'Alex',
                'online': True
            },
            custom_message_type="text-message"
        ).sync()
        print("Publish timetoken: %d" % envelope.result.timetoken)
    except PubNubException as e:
        print(f"Error: {e}")

def main():
    # Configuration for PubNub instance
    pn_config = PNConfiguration()
    pn_config.subscribe_key = os.getenv('SUBSCRIBE_KEY', 'demo')
    pn_config.publish_key = os.getenv('PUBLISH_KEY', 'demo')
    pn_config.user_id = os.getenv('USER_ID', 'my_custom_user_id')

    # Initialize PubNub client
    pubnub = PubNub(pn_config)

    # Publish message
    publish_message(pubnub)

if __name__ == "__main__":
    main()
```

:::note Subscribe to the channel
Before running the above publish example, either using the [Debug Console](https://www.pubnub.com/docs/console/) or in a separate script running in a separate terminal window, [subscribe to the same channel](#subscribe) that is being published to.
:::

### Returns

The `publish()` operation returns an `Envelope` which contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| result | [PNPublishResult](#pnpublishresult) | A string representation of the result and the timetoken when the message was published. |
| status | `PNStatus` | A status object with additional information. |

#### PNPublishResult

```json
Publish success with timetoken 17193163560057793
```

### Other examples

#### Publish with metadata

```python
def publish_callback(result, status):
    pass
    # handle publish result, status always present, result if successful
    # status.is_error() to see if error happened

pubnub.publish().channel("my_channel").message(["hello", "there"]) \
    .meta({'name': 'Alex'}).pn_async(publish_callback)
```

## Fire

The fire endpoint sends a message to Functions event handlers and Illuminate. The message goes directly to handlers registered on the target channel and triggers their execution. The handler can read the request body. Messages sent via `fire()` aren't replicated to subscribers and aren't stored in history.

### Method(s)

To `Fire a message` you can use the following method(s) in the Python SDK:

```python
pubnub.fire() \
    .channel(String) \
    .message(Object) \
    .use_post(Boolean) \
    .meta(Object)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Destination of `message` (channel ID). |
| `message` *Type: ObjectDefault: n/a | The payload. |
| `use_post`Type: BooleanDefault: `False` | Use POST to publish. |
| `meta`Type: ObjectDefault: `None` | Meta data object which can be used with the filtering ability. |

### Sample code

#### Fire a message to a channel

##### Builder Pattern

```python
envelope = pubnub.fire() \
    .channel('my_channel') \
    .message('hello there') \
    .use_post(True) \
    .sync()
print(f'fire timetoken: {envelope.result.timetoken}')
```

##### Named Arguments

```python
fire = pubnub.fire(channel="my_channel", message='hello there').sync()
print(f'fire timetoken: {fire.result.timetoken}')
```

### Returns

The `fire()` operation returns an `Envelope` which contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| result | [PNFireResult](#pnfireresult) | A string representation of the result and the timetoken when the message was fired. |
| status | `PNStatus` | A status object with additional information. |

#### PNFireResult

```json
Fire success with timetoken 17193163560057793
```

## Signal

The `signal()` function sends a signal to all subscribers of a channel.

Signals have a 64‑byte payload limit (payload only, not URI or headers). For larger payloads, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Method(s)

To `Signal a message` you can use the following method(s) in the Python SDK:

```python
pubnub.signal() \
    .message(Object) \
    .custom_message_type(String) \
    .channel(String)
```

| Parameter | Description |
| --- | --- |
| `message` *Type: Object | The payload. |
| `custom_message_type`Type: String | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |
| `channel` *Type: String | Destination of `message` (channel ID). |

### Sample code

#### Signal a message to a channel

##### Builder Pattern

```python
envelope = pubnub.signal() \
    .channel('some_channel') \
    .message('foo') \
    .custom_message_type('text-message') \
    .sync()
```

##### Named Arguments

```python
signal = pubnub.signal(channel="my_channel", message='hello there', custom_message_type='text-message').sync()
print(f'signal timetoken: {signal.result.timetoken}')
```

### Returns

The `signal()` operation returns an `Envelope` which contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| result | [PNSignalResult](#pnsignalresult) | A string representation of the result and the timetoken when the signal was sent. |
| status | `PNStatus` | A status object with additional information. |

#### PNSignalResult

```json
Signal success with timetoken 17193165584676126
```

## Subscribe

Subscribe opens a TCP socket and listens for messages and events on a specified entity or set of entities. Configure the `subscribeKey` during [initialization](https://www.pubnub.com/docs/sdks/python/api-reference/configuration).

:::tip Conceptual overview
For more general information about subscriptions, refer to [Subscriptions](https://www.pubnub.com/docs/general/channels/subscribe).
:::

Entities are [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) that provide access to their encapsulated APIs. You can subscribe using the PubNub client object or directly on a specific entity:

* [ChannelRepresentation](#create-channels)
* [ChannelGroupRepresentation](#create-channel-groups)
* [UserMetadataRepresentation](#create-user-metadata)
* [ChannelMetadataRepresentation](#create-channel-metadata)

A newly subscribed client receives messages after `subscribe()` completes. Enable [automatic retries](https://www.pubnub.com/docs/sdks/python/api-reference/configuration#configuration) to reconnect and retrieve available messages if a client disconnects.

### Subscription scope

Subscriptions let you attach listeners for specific real-time update types. Your app receives messages and events through those listeners. There are two types:

* [Subscription](#create-a-subscription): created from an entity and scoped to that entity (for example, a particular channel)
* [SubscriptionSet](#create-a-subscription-set): created from the PubNub client and scoped to the client (for example, all subscriptions created on a single `pubnub` object). A set can include one or more subscriptions.

The event listener is a single point through which your app receives all the messages, signals, and events in the entities you subscribed to. For information on adding event listeners, refer to [Event listeners](#event-listeners).

### Create a subscription

An entity-level `Subscription` allows you to receive messages and events for only that entity for which it was created. Using multiple entity-level `Subscription`s is useful for handling various message/event types differently in each channel.

```python
# entity-based, local-scoped
subscription = pubnub.channel(f'{channel}').subscription(with_presence: bool = False)
```

| Parameter | Description |
| --- | --- |
| `with_presence`Type: `bool` | Whether presence updates for `userId`s should be delivered through the listener streams. For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel). |

### Create a subscription set

A client-level `SubscriptionSet` allows you to receive messages and events for all entities. A single `SubscriptionSet` is useful for similarly handling various message/event types in each channel.

```python
# client-based, general-scoped
subscription_set = pubnub.subscription_set(subscriptions: List[PubNubSubscription])
```

| Parameter | Description |
| --- | --- |
| `subscriptions` *Type: `List[PubNubSubscription]` | Channels/Channel group subscriptions. |

### Method(s)

`Subscription` and `SubscriptionSet` use the same `subscribe()` method.

#### Subscribe

To subscribe, you can use the following method in the Python SDK:

```python
subscription.subscribe(timetoken: Optional[int] = None, region: Optional[str] = None,)
```

| Parameter | Description |
| --- | --- |
| `timetoken`Type: `int` | Timetoken from which to return any available cached messages. Message retrieval with timetoken is not guaranteed and should only be considered a best-effort service. If the value is not a 17-digit number, the provided value will be ignored. |
| `region`Type: String | The region the message was published in. |

##### Sample code

```python
# single channel subscription
channel = pubnub.channel(f'{channel}')
t1_subscription = channel.subscription()
t1_subscription.subscribe()

# multiple channel subscription
channel_1 = pubnub.channel(channel).subscription()
channel_2 = pubnub.channel(f'{channel}.2').subscription(with_presence=True)
channel_x = pubnub.channel(f'{channel}.*').subscription(with_presence=True)

group = pubnub.channel_group('group-test').subscription()

subscription_set = pubnub.subscription_set([channel_1, channel_2, channel_x, group])

set_subscription = subscription_set.subscribe()
```

##### Returns

The `subscribe()` method doesn't have a return value.

## Entities

Entities are subscribable objects for which you can receive real-time updates (messages, events, etc).

* [PubNubChannel](#create-channels)
* [PubNubChannelGroup](#create-channel-groups)
* [PubNubUserMetadata](#create-user-metadata)
* [PubNubChannelMetadata](#create-channel-metadata)

### Create channels

This method returns a local `PubNubChannel` entity.

```python
pubnub.channel(String)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | The ID of the [channel](https://www.pubnub.com/docs/general/channels/overview) to create a subscription of. |

#### Sample code

```python
pubnub.channel(f'{channel1}')
```

### Create channel groups

This method returns a local `PubNubChannelGroup` entity.

```python
pubnub.channel_group(String)
```

| Parameter | Description |
| --- | --- |
| `channel_group` *Type: String | The name of the [channel group](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to create a subscription of. |

#### Sample code

```python
pubnub.channel_group("channelGroupName")
```

### Create channel metadata

This method returns a local `PubNubChannelMetadata` entity.

```python
pubnub.channel_metadata(String)
```

| Parameter | Description |
| --- | --- |
| `channel_metadata` *Type: String | The String identifier of the [channel metadata](https://www.pubnub.com/docs/general/metadata/channel-metadata) object to create a subscription of. |

#### Sample code

```python
pubnub.channel_metadata("channelMetadata")
```

### Create user metadata

This method returns a local `PubNubUserMetadata` entity.

```python
pubnub.user_metadata(String)
```

| Parameter | Description |
| --- | --- |
| `user_metadata` *Type: String | The String identifier of the [user metadata](https://www.pubnub.com/docs/general/metadata/users-metadata) object to create a subscription of. |

#### Sample code

```python
pubnub.userMetadata("user_metadata")
```

## Event listeners

Messages and events are received in your app using a listener. This listener allows a single point to receive all messages, signals, and events.

You can attach listeners to the instances of [Subscription](#create-a-subscription), [SubscriptionSet](#create-a-subscription-set), and, in the case of the connection status, the PubNub client.

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/general/channels/subscribe-filters) to filter messages server-side before they reach your listener.
:::

### Add listeners

You can implement multiple listeners or register an event-specific listener that receives only a selected type, like `message` or `file`.

#### Method(s)

```python
# Add event-specific listeners

# using closure for reusable listener
def on_message(listener):
    def message_callback(message):
        print(f"\033[94mMessage received on: {listener}: \n{message.message}\033[0m\n")
    return message_callback

# without closure
def on_message_action(message_action):
    print(f"\033[5mMessageAction received: \n{message_action.value}\033[0m\n")

def on_presence(listener):
    def presence_callback(presence):
        print(f"\033[0;32mPresence received on: {listener}: \t{presence.uuid} {presence.event}s "
              f"{presence.subscription or presence.channel}\033[0m")
    return presence_callback

def on_status(listener):
    def status_callback(status):
        print(f"\033[92mStatus received on: {listener}: \t{status.category.name}\033[0m")
    return status_callback

def on_signal(listener):
    def signal_callback(signal):
        print(f"\033[0;36mSignal received on: {listener}: \n{signal.publisher} says: \t{signal.message}\033[0m")
    return signal_callback

def on_channel_metadata(listener):
    def channel_metadata_callback(channel_meta):
        print(f"\033[0;36mChannel metadata received on: {listener}: \n{channel_meta.__dict__}\033[0m")
    return channel_metadata_callback

def on_user_metadata(listener):
    def user_metadata_callback(user_meta):
        print(f"\033[0;36mUser metadata received on: {listener}: \n{user_meta.__dict__}\033[0m")
    return user_metadata_callback

def on_file(listener):
    def file_callback(files):
        print(f"\033[0;36mFile received on: {listener}: \n{user_meta.__dict__}\033[0m")
    return file_callback

subscription.on_message = on_message('message_listener')
subscription.on_message_action = on_message_action

# add generic listener
class PrintListener(SubscribeCallback):
    def status(self, _, status):
        print(f'\033[92mPrintListener.status:\n{status.category.name}\033[0m')

    def message(self, _, message):
        print(f'\033[94mPrintListener.message:\n{message.message}\033[0m')

    def presence(self, _, presence):
        print(f'PrintListener.presence:\n{presence.uuid} {presence.event}s '
              f'{presence.subscription or presence.channel}\033[0m')

    def signal(self, _, signal):
        print(f'PrintListener.signal:\n{signal.message} from {signal.publisher}\033[0m')

    def channel(self, _, channel):
        print(f'\033[0;37mChannel Meta:\n{channel.__dict__}\033[0m')

    def uuid(self, _, uuid):
        print(f'User Meta:\n{uuid.__dict__}\033[0m')

    def membership(self, _, membership):
        print(f'Membership:\n{membership.__dict__}\033[0m')

    def message_action(self, _, message_action):
        print(f'PrintListener.message_action {message_action}\033[0m')

    def file(self, _, file_message):
        print(f' {file_message.__dict__}\033[0m')

subscription.add_listener(PrintListener())
```

#### Sample code

```python
subscription = pubnub.channel(f'{channel1}').subscription()

def on_message(listener):
    def message_callback(message):
        print(f"\033[94mMessage received on: {listener}: \n{message.message}\033[0m\n")
    return message_callback

def on_message_action(message_action):
    print(f"\033[5mMessageAction received: \n{message_action.value}\033[0m\n")

subscription.on_message = on_message('message_listener')
subscription.on_message_action = on_message_action

subscription.subscribe()

subscription_set = pubnub.subscription_set(channels=["channel", "channel2"],
                                          channel_groups=["cg_1"],
                                          with_presence=True)

subscription_set.subscribe()
```

### Add connection status listener

The PubNub client has a listener dedicated to handling connection status updates.

:::warning Client scope
This listener is only available on the PubNub object.
:::

#### Method(s)

```python
pubnub.add_listener()
```

#### Sample code

```python
class PrintListener(SubscribeListener):
    def status(self, pubnub, status):
        print(f'Status:\n{status.__dict__}')

    def message(self, pubnub, message):
        pass

    def presence(self, pubnub, presence):
        pass

listener = PrintListener()
pubnub.add_listener(listener)
```

#### Returns

The subscription status. For information about available statuses, refer to [SDK statuses](https://www.pubnub.com/docs/general/setup/connection-management#sdk-statuses).

## Unsubscribe

Stop receiving real-time updates from a [Subscription](#create-a-subscription) or a [SubscriptionSet](#create-a-subscription-set).

### Method(s)

```python
subscription.unsubscribe()

subscription_set.unsubscribe()
```

### Sample code

```python
channel = pubnub.channel(f'{channel}')
t1_subscription = channel.subscription()
t1_subscription.subscribe()

subscription_set1 = pubnub.subscription_set(channels=['channel1', 'channel2'])
subscription_set.subscribe()

t1_subscription1.unsubscribe()
subscription_set.unsubscribe()
```

### Returns

None

## Unsubscribe all

Stop receiving real-time updates from all data streams and remove the entities associated with them.

:::warning Client scope
This method is only available on the PubNub object.
:::

### Method(s)

```python
pubnub.unsubscribe_all()
```

### Sample code

```python
channel = pubnub.channel(f'{channel}')
t1_subscription = channel.subscription()
t1_subscription.subscribe()

subscription_set1 = pubnub.subscription_set(channels=['channel1', 'channel2'])
subscription_set.subscribe()

t1_subscription1.unsubscribe()
subscription_set.unsubscribe()

pubnub.unsubscribe_all()
```

### Returns

None

## Subscribe (old)

:::warning Not recommended
The use of this method is discouraged. Use [Subscribe](#subscribe) instead.
:::

#### Receive messages

Your app receives messages and events via event listeners. The event listener is a single point through which your app receives all the messages, signals, and events that are sent in any channel you are subscribed to.

For more information about adding a listener, refer to the [Event Listeners](https://www.pubnub.com/docs/sdks/python/api-reference/configuration#event-listeners) section.

#### Description

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified `channel` ID. To subscribe to a `channel` ID the client must send the appropriate `subscribe_key` at initialization.

By default a newly subscribed client will only receive messages published to the channel after the `subscribe()` call completes. If a client gets disconnected from a channel, it can automatically attempt to reconnect to that `channel` ID and retrieve any available messages that were missed during that period. This can be achieved by setting `setReconnectionPolicy` to `PNReconnectionPolicy.LINEAR`, when [initializing](https://www.pubnub.com/docs/sdks/python/api-reference/configuration#initialization) the client.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

To `Subscribe to a channel` you can use the following method(s) in the Python SDK:

```python
pubnub.subscribe() \
    .channels(String|List|Tuple) \
    .channel_groups(String|List|Tuple) \
    .with_timetoken(Int) \
    .with_presence() \
    .execute()
```

| Parameter | Description |
| --- | --- |
| `channels`Type: String | List | Tuple | Subscribe to `channels`, Either `channel` ID or `channel_group` is required. |
| `channel_groups`Type: String | List | Tuple | Subscribe to `channel_groups`, Either `channel` ID or `channel_group` is required. |
| `timetoken`Type: Int | Pass a `timetoken`. |
| `with_presence`Type: Command | Also subscribe to related presence information. |

#### Sample code

Subscribe to a channel:

```python
pubnub.subscribe() \
    .channels('my_channel') \
    .execute()
```

:::note Event listeners
The response of the call is handled by adding a Listener. Please see the [Listeners section](https://www.pubnub.com/docs/sdks/python#add-event-listeners) for more details. Listeners should be added before calling the method.
:::

#### Returns

:::note PNMessageResult
`PNMessageResult` is returned in the [Listeners](https://www.pubnub.com/docs/sdks/python#add-event-listeners)
:::

The `subscribe()` operation returns a `PNStatus` for messages which contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| `category` | PNStatusCategory | See the [Python SDK listener categories](https://www.pubnub.com/docs/sdks/python/status-events). |
| `is_error` | Boolean | This is `True` if an error occurred in the execution of the operation. |
| `error_data` | PNErrorData | Error data of the exception (if `Error` is `True`). |
| `status_code` | int | Status code of the execution. |

The `subscribe()` operation returns a `PNMessageResult` for messages which contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| `message` | Object | The `message` sent on the `channel` ID. |
| `subscription` | String | The channel group or wildcard `subscription` match (if exists). |
| `channel` | String | The `channel` ID for which the message belongs. |
| `timetoken` | Int | `Timetoken` for the message. |
| `user_metadata` | Dictionary | User `metadata`. |

The `subscribe()` operation returns a `PNPresenceEventResult` from presence which contains the following operations:

| Field | Type | Description |
| --- | --- | --- |
| `event` | String | Events like `join`, `leave`, `timeout`, `state-change`. |
| `uuid` | String | `uuid` for event. |
| `timestamp` | Int | `timestamp` for event. |
| `occupancy` | Int | Current `occupancy`. |
| `subscription` | String | The channel group or wildcard `subscription` match (if exists). |
| `channel` | String | The `channel` ID for which the message belongs. |
| `timetoken` | Int | `timetoken` of the message. |
| `user_metadata` | Dictionary | User `metadata`. |

The `subscribe()` operation returns a `PNSignalResult` for signals which contains the following operations:

| Field | Type | Description |
| --- | --- | --- |
| `timetoken` | Int | An int representation of the `timetoken` when Signal was sent. |
| `channel` | String | The `channel` ID on which Signal occurred. |
| `publisher` | String | ID of the sender. |
| `message` | Object | The payload. |

#### Other examples

##### Basic subscribe with logging

```python
import logging
import pubnub

from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub, SubscribeListener

pubnub.set_stream_logger('pubnub', logging.DEBUG)

pnconfig = PNConfiguration()

pnconfig.subscribe_key = 'demo'
pnconfig.publish_key = 'demo'

pubnub = PubNub(pnconfig)

pubnub.add_listener(SubscribeListener())
pubnub.subscribe().channels("my_channel").execute()
```

:::note Logging setup
For information on how to properly enable logging at the package level and the correct function call syntax, see the [Logging](https://www.pubnub.com/docs/sdks/python/logging) documentyarn.
:::

##### Subscribing to multiple channels

It's possible to subscribe to more than one channel using the [Multiplexing](https://www.pubnub.com/docs/general/channels/subscribe#channel-multiplexing) feature. The example shows how to do that using an array to specify the channel names.

:::note Alternative subscription methods
You can also use [Wildcard Subscribe](https://www.pubnub.com/docs/general/channels/subscribe#wildcard-subscribe) and [Channel Groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to subscribe to multiple channels at a time. To use these features, the *Stream Controller* add-on must be enabled on your keyset in the [Admin Portal](https://admin.pubnub.com).
:::

```python
pubnub.subscribe() \
    .channels(["my_channel1", "my_channel2"]) \
    .execute()
```

##### Subscribing to a Presence channel

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending `-pnpres` to the channel name. For example the channel named `my_channel` would have the presence channel named `my_channel-pnpres`.

```python
pubnub.subscribe()\
    .channels("my_channel")\
    .with_presence()\
    .execute()
```

##### Sample Responses

###### Join event

```python
if envelope.event == 'join':
    envelope.uuid # 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    envelope.timestamp # 1345546797
    envelope.occupancy # 2
```

###### Leave event

```json
{
    "action" : "leave",
    "timestamp" : 1345549797,
    "uuid" : "175c2c67-b2a9-470d-8f4b-1db94f90e39e",
    "occupancy" : 1
}
```

###### Timeout event

```python
if envelope.event == 'timeout':
    envelope.uuid # 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    envelope.timestamp # 1345546797
    envelope.occupancy # 0
```

###### State change event

```python
if envelope.event == 'state-change':
    envelope.uuid # 76c2c571-9a2b-d074-b4f8-e93e09f49bd
    envelope.timestamp # 1345546797
    envelope.user_metadata # {'is_typing': True}
```

##### Interval event

```json
{
    "action":"interval",
    "timestamp":1474396578,
    "occupancy":2
}
```

When a channel is in interval mode with `presence_deltas` `pnconfig` flag enabled, the interval message may also include the following fields which contain an array of changed UUIDs since the last interval message.

* joined
* left
* timedout

For example, this interval message indicates there were 2 new UUIDs that joined and 1 timed out UUID since the last interval:

```json
{
    "action" : "interval",
    "occupancy" : <# users in channel>,
    "timestamp" : <unix timestamp>,
    "joined" : ["uuid2", "uuid3"],
    "timedout" : ["uuid1"]
}
```

If the full interval message is greater than `30KB` (since the max publish payload is `∼32KB`), none of the extra fields will be present. Instead there will be a `here_now_refresh` boolean field set to `True`. This indicates to the user that they should do a `hereNow` request to get the complete list of users present in the channel.

```json
{
    "action" : "interval",
    "occupancy" : <# users in channel>,
    "timestamp" : <unix timestamp>,
    "here_now_refresh" : True
}
```

##### Wildcard subscribe to channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/) (with Enable Wildcard Subscribe checked). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

Wildcard subscribes allow the client to subscribe to multiple channels using wildcard. For example, if you subscribe to `a.*` you will get all messages for `a.b`, `a.c`, `a.x`. The wildcarded `*` portion refers to any portion of the channel string name after the `dot (.)`.

```python
pubnub.subscribe() \
    .channels("foo.*") \
    .execute()
```

:::note Wildcard grants and revokes
Only one level (`a.*`) of wildcarding is supported. If you grant on `*` or `a.b.*`, the grant will treat `*` or `a.b.*` as a single channel named either `*` or `a.b.*`. You can also revoke permissions from multiple channels using wildcards but only if you previously granted permissions using the same wildcards. Wildcard revokes, similarly to grants, only work one level deep, like `a.*`.
:::

##### Subscribing with state

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

:::note Required User ID
Always set the `user_id` to uniquely identify the user or device that connects to PubNub. This `user_id` should be persisted, and should remain unchanged for the lifetime of the user or the device. If you don't set the `user_id`, you won't be able to connect to PubNub.
:::

```python
from pubnub.enums import PNStatusCategory

from pubnub.pubnub import SubscribeListener, PubNub

class MySubscribeListener(SubscribeListener):
    def __init__(self):
        if status.category == PNStatusCategory.PNConnectedCategory:
            state = {
                'field_a': 'awesome',
                'field_b': 10
            }
            envelope = pubnub.set_state().channels('my_channel').\
                channel_groups('awesome_channel_groups').state(state).sync()

        else:
            pass

    def status(self, pubnub, status):
        pass

    def message(self, pubnub, message):
        pass

    def presence(self, pubnub, presence):
        pass

pubnub = PubNub(pnconfig)

my_listener = MySubscribeListener()
pubnub.add_listener(my_listener)

pubnub.subscribe().channels("my_channel").execute()
```

##### Subscribe to a channel group

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```python
pubnub.subscribe() \
    .channel_groups("awesome_channel_group") \
    .execute()
```

##### Subscribe to the Presence channel of a channel group

:::note Requires Stream Controller and Presence add-ons
This method requires both the *Stream Controller* and *Presence* add-ons are enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```python
pubnub.subscribe() \
    .channel_groups("awesome_channel_group") \
    .with_presence() \
    .execute()
```

#### Event listeners

You can be notified of connectivity status, message and presence notifications via the listeners.

Listeners should be added before calling the method.

##### Add listeners

```python
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNOperationType, PNStatusCategory

class MySubscribeCallback(SubscribeCallback):
    def message(self, pubnub, message):
        print("Message channel: %s" % message.channel)
        print("Message subscription: %s" % message.subscription)
        print("Message timetoken: %s" % message.timetoken)
        print("Message payload: %s" % message.message)
        print("Message publisher: %s" % message.publisher)

    def presence(self, pubnub, presence):
        # Can be join, leave, state-change, timeout, or interval
        print("Presence event: %s" % presence.event)

        # The channel to which the message was published
        print("Presence channel: %s" % presence.channel)

        # Number of users subscribed to the channel
        print("Presence occupancy: %s" % presence.occupancy)

        # User state
        print("Presence state: %s" % presence.state)

        # Channel group or wildcard subscription match, if any
        print("Presence subscription: %s" % presence.subscription)

        # UUID to which this event is related
        print("Presence UUID: %s" % presence.uuid)

        # Publish timetoken
        print("Presence timestamp: %s" % presence.timestamp)

        # Current timetoken
        print("Presence timetoken: %s" % presence.timetoken)

        # List of users that have joined the channel (if event is 'interval')
        joined = presence.join

        # List of users that have left the channel (if event is 'interval')
        left = presence.leave

        # List of users that have timed-out off the channel (if event is 'interval')
        timed_out = presence.timeout

    def status(self, pubnub, status):

        # The status object returned is always related to subscribe but could contain
        # information about subscribe, heartbeat, or errors
        # use the operationType to switch on different options
        if status.operation == PNOperationType.PNSubscribeOperation \
                or status.operation == PNOperationType.PNUnsubscribeOperation:
            if status.category == PNStatusCategory.PNConnectedCategory:
                pass
                # This is expected for a subscribe, this means there is no error or issue whatsoever
            elif status.category == PNStatusCategory.PNReconnectedCategory:
                pass
                # This usually occurs if subscribe temporarily fails but reconnects. This means
                # there was an error but there is no longer any issue
            elif status.category == PNStatusCategory.PNDisconnectedCategory:
                pass
                # This is the expected category for an unsubscribe. This means there
                # was no error in unsubscribing from everything
            elif status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
                pass
                # This is usually an issue with the internet connection, this is an error, handle
                # appropriately retry will be called automatically
            elif status.category == PNStatusCategory.PNAccessDeniedCategory:
                pass
                # This means that Access Manager does not allow this client to subscribe to this
                # channel and channel group configuration. This is another explicit error
            else:
                pass
                # This is usually an issue with the internet connection, this is an error, handle appropriately
                # retry will be called automatically
        elif status.operation == PNOperationType.PNSubscribeOperation:
            # Heartbeat operations can in fact have errors, so it is important to check first for an error.
            # For more information on how to configure heartbeat notifications through the status
            # PNObjectEventListener callback, consult http://www.pubnub.com/docs/sdks/python/api-reference/configuration#configuration
            if status.is_error():
                pass
                # There was an error with the heartbeat operation, handle here
            else:
                pass
                # Heartbeat operation was successful
        else:
            pass
            # Encountered unknown status type

    def signal(self, pubnub, signal):
        print("Signal channel: %s" % signal.channel)
        print("Signal subscription: %s" % signal.subscription)
        print("Signal timetoken: %s" % signal.timetoken)
        print("Signal payload: %s" % signal.message)
        print("Signal publisher: %s" % signal.publisher)

    def message_action(self, pubnub, message_action):
        print("Message action type: %s" % message_action.type)
        print("Message action value: %s" % message_action.value)
        print("Message action uuid: %s" % message_action.uuid)
        print("Message action action_timetoken: %s" % message_action.action_timetoken)
        print("Message action message_timetoken: %s" % message_action.message_timetoken)

pubnub.add_listener(MySubscribeCallback())
```

##### Remove listeners

```python
my_listener = MySubscribeCallback()

pubnub.add_listener(my_listener)

# some time later
pubnub.remove_listener(my_listener)
```

##### Handling disconnects

```python
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNStatusCategory

class HandleDisconnectsCallback(SubscribeCallback):
    def status(self, pubnub, status):
        if status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
            # internet got lost, do some magic and call reconnect when ready
            pubnub.reconnect()
        elif status.category == PNStatusCategory.PNTimeoutCategory:
            # do some magic and call reconnect when ready
            pubnub.reconnect()
        else:
            logger.debug(status)

    def presence(self, pubnub, presence):
        pass

    def message(self, pubnub, message):
        pass

    def signal(self, pubnub, signal):
        pass

disconnect_listener = HandleDisconnectsCallback()

pubnub.add_listener(disconnect_listener)
```

##### Listener status events

| Category | Description |
| --- | --- |
| `PNTimeoutCategory` | Failure to establish a connection to PubNub due to a timeout. |
| `PNBadRequestCategory` | The server responded with a bad response error because the request is malformed. |
| `PNNetworkIssuesCategory` | A subscribe event experienced an exception when running. The SDK isn't able to reach PubNub servers. This may be due to many reasons, such as: the machine or device isn't connected to the internet; the internet connection has been lost; your internet service provider is having trouble; or, perhaps the SDK is behind a proxy. |
| `PNReconnectedCategory` | The SDK was able to reconnect to PubNub. |
| `PNConnectedCategory` | SDK subscribed with a new mix of channels. This is fired every time the `channel` ID or `channel group` mix changes. |
| `PNUnexpectedDisconnectCategory` | Previously started subscribe loop did fail and at this moment client disconnected from real-time data channels. |
| `PNUnknownCategory` | Returned when the subscriber gets a non-200 HTTP response code from the server. |

`SubscribeListener` should not be used with high-performance sections of your app.

## Unsubscribe (old)

:::warning Not recommended
The use of this method is discouraged. Use [Unsubscribe](#unsubscribe) instead.
:::

When subscribed to a single channel, this function causes the client to issue a `leave` from the `channel` and close any open socket to the PubNub Network. For multiplexed channels, the specified `channel`(s) will be removed and the socket remains open until there are no more channels remaining in the list.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

To `Unsubscribe from a channel` you can use the following method(s) in the Python SDK:

```python
pubnub.unsubscribe() \
    .channels(String|List|Tuple) \
    .channel_groups(String|List|Tuple) \
    .execute()
```

| Parameter | Description |
| --- | --- |
| `channels`Type: String | List | Tuple | Subscribe to `channels`, Either `channel` ID or `channel_group` is required. |
| `channel_groups`Type: String | List | Tuple | Subscribe to `channel_groups`, Either `channel` ID or `channel_group` is required |

#### Sample code

Unsubscribe from a channel:

```python
pubnub.unsubscribe() \
    .channels("my_channel") \
    .execute()
```

:::note Event listeners
The response of the call is handled by adding a Listener. Please see the [Listeners section](https://www.pubnub.com/docs/sdks/python#add-event-listeners) for more details. Listeners should be added before calling the method.
:::

#### Response

The output below demonstrates the response to a successful call:

```python
if envelope.event == 'leave':
    envelope.uuid # 175c2c67-b2a9-470d-8f4b-1db94f90e39e
    envelope.timestamp # 1345546797
    envelope.occupancy # 2
```

#### Other examples

##### Unsubscribing from multiple channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```python
pubnub.unsubscribe() \
    .channels(["my_channel1", "my_channel2"]) \
    .execute()
```

###### Example response

```json
{
    "action" : "leave"
}
```

##### Unsubscribe from a channel group

```python
pubnub.unsubscribe() \
    .channels_groups(["my_group1", "my_group2") \
    .execute()
```

**Example Response:** [](#unsubscribe-example-2-response)

```javascript
{
    "action": "leave"
}
```

## Unsubscribe all (old)

:::warning Not recommended
The use of this method is discouraged. Use [Unsubscribe All](#unsubscribe-all) instead.
:::

Unsubscribe from all channels and all channel groups.

#### Method(s)

```python
pubnub.unsubscribe_all()
```

#### Sample code

```python
pubnub.unsubscribe_all()
```

#### Returns

None

## Terms in this document

* **Access Manager** - A cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and user IDs.
* **Action** - The type of activity (procedure) to execute when a condition is satisfied (for example, sending a message).
* **Billing alert notification** - A means of informing a user that a billing alert has been triggered. Before notifications can happen, a billing alert must be triggered first.
* **Business Object** - A container for data fields and metrics that defines aggregations and data sources.
* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Condition** - A requirement that must be satisfied or evaluated to true for an action to be executed. Input in a decision table.
* **Cryptor** - An implementation of a specific cryptographic algorithm used for data encryption/decryption that adheres to a standard interface.
* **Dashboard** - A collection of widgets (charts) that give an overview of the metrics one is evaluating.
* **Data fields** - Data you want Illuminate to track. These can be quantitative (measures), like "Number" or "Timestamp" or qualitative (dimensions) values, like "String" that can be used to categorize and segment data. Data fields can be aggregated and calculated.
* **Decision** - A collection (or decision table) of conditions and actions. When conditions are satisfied, the corresponding actions are triggered as per defined rules.
* **End Customer** - A customer of a PubNub partner. End customers do not have direct access to the Admin Portal. Instead, they interact with PubNub products—such as Illuminate—through the partner’s portal, where PubNub services are embedded. They can create PubNub objects only within this partner-provided environment.
* **Entity** - A subscribable object within a PubNub SDK that allows you to perform context-specific operations.
* **Listener** - A function or objectthat reacts to events or messages, like new chat messages or connection updates, letting your app respond in real-time.
* **Mapped/Unmapped** - Whether the data source for a data field has been defined or the action has been configured.
* **MCP Server** - A Model Context Protocol server that coordinates communication and synchronization between AI agents, clients, or services, such as Cursor IDE and Windsurf.
* **Message** - A unit of data transmitted between clients or between a client and a server in PubNub, containing information such as text, binary data, or structured data formats like JSON. Messages are sent over channels and can be tracked for delivery and read status.
* **Metric** - What exactly is evaluated using measures and dimensions (collectively called data fields), as well as aggregation functions.
* **Module** - A Functions v1 container that groups related functions for configuration and deployment on an app’s keysets.
* **Origin** - The subdomain used to establish a connection to the PubNub network that allows your application's traffic to appear like it's coming from your own domain.
* **Package** - A Functions v2 container that groups Functions, tracks Revisions, and is deployed to keysets.
* **Partner** - A PubNub customer who resells PubNub products, such as Illuminate, to their own customers. Partners have access to the Admin Portal, enabling them to create and manage PubNub objects for themselves or on behalf of their end customers.
* **Publish Key** - A unique identifier that allows your application to send messages to PubNub channels. It's part of your app's credentials and should be kept secure.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
* **Push token** - A device identifier issued by a push provider (APNs or FCM) used to register a device for receiving mobile push notifications.
* **Rule** - A definition (row in a decision table) stating which action should be triggered for which condition.
* **Service Integration** - A machine identity that represents a program or service consuming the Admin API, scoped to your account and authenticated using expirable API keys with configurable permissions.
* **Signal** - A non-persistent message limited to 64 bytes designed for high-volume usecases where the the most recent data is relevant, like GPS location updates.
* **Subscribe Key** - A unique identifier that allows your application to receive messages from PubNub channels. It's part of your app's credentials and should be kept secure.
* **Timetoken** - A unique identifier for each message that represents the number of 100-nanosecond intervals since January 1, 1970, for example, 16200000000000000.
* **Trigger details** - A set of predefined criteria for a given billing alert. When met, billing alert notifications are generated.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.
* **Vibe Coding** - A way to build applications in an intuitive, relaxed, and improvisational manner, using AI tools and natural language descriptions.