---
source_url: https://www.pubnub.com/docs/sdks/python/api-reference/presence
title: Presence API for Python SDK
updated_at: 2026-06-23T11:45:47.793Z
sdk_name: PubNub Python SDK
sdk_version: 10.7.1
---

> 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


# Presence API for Python SDK

PubNub Python SDK, use the latest version: 10.7.1

Install:

```bash
pip install pubnub@10.7.1
```

Presence lets you track who is online or offline and store custom state information. Presence shows:

* When a user has joined or left a channel
* How many users are subscribed to a particular channel (occupancy)
* Which channels a user or device is subscribed to
* Presence state associated with these users

Learn more about our Presence feature in the [Presence overview](https://www.pubnub.com/docs/general/presence/overview).

:::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)
:::

## Here now

:::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).
:::

This method returns information about the current state of a channel, including a list of unique user IDs (universally unique identifiers, UUIDs) currently subscribed to the channel and the total occupancy count of the channel.

:::note Cache
This method has a 3-second response cache time.
:::

### Method(s)

To call `Here Now` you can use the following method(s) in the Python SDK:

```python
pubnub.here_now() \
    .channels(String|List|Tuple) \
    .channel_groups(String|List|Tuple) \
    .include_state(Boolean) \
    .include_uuids(Boolean) \
    .limit(Integer) \
    .offset(Integer)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channels | String | Optional |  | The `channels` to get the here now details. |
| channel_groups | String | Optional |  | The `channel groups` to get the here now details. Wildcards are not supported. |
| include_state | Boolean | Optional | `False` | If `True`, the response will include the presence states of the users for channels/channelGroups. |
| include_uuids | Boolean | Optional | `True` | If `True`, the response will include the UUIDs of the connected clients. |
| limit | Integer | Optional | `1000` | Maximum number of occupants to return per channel. Valid range: `0-1000`. Use `0` to get occupancy counts without user details. |
| offset | Integer | Optional | `None` | Zero-based starting index for pagination. Returns occupants starting from this position in the list. Must be `>= 0`. Requires `limit > 0`. Use with `limit` to paginate through large occupant lists. |

### Sample code

#### Get a list of UUIDs subscribed to 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

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

    # Initialize PubNub client
    pubnub = PubNub(pn_config)

    # Get here_now details
    here_now = pubnub.here_now() \
        .channels(["my_channel", "demo"]) \
        .include_uuids(True) \
        .sync()

    if here_now.status.is_error():
        print(f"Error: {here_now.status.error}")
        return

    for channel_data in here_now.result.channels:
        print("---")
        print(f"Channel: {channel_data.channel_name}")
        print(f"Occupancy: {channel_data.occupancy}")

        for occupant in channel_data.occupants:
            print(f"UUID: {occupant.uuid}, State: {occupant.state}")

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

###### Named Arguments

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

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

    # Initialize PubNub client
    pubnub = PubNub(pn_config)

    # Get here_now details
    here_now = pubnub.here_now(
        channels=["my_channel", "demo"],
        include_uuids=True
    ).sync()

    if here_now.status.is_error():
        print(f"Error: {here_now.status.error}")
        return

    for channel_data in here_now.result.channels:
        print("---")
        print(f"Channel: {channel_data.channel_name}")
        print(f"Occupancy: {channel_data.occupancy}")

        for occupant in channel_data.occupants:
            print(f"UUID: {occupant.uuid}, State: {occupant.state}")

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

### Returns

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

| Field | Type | Description |
| --- | --- | --- |
| result | [PNHereNowResult](#pnherenowresult) | A detailed object containing the result of the operation. |
| status | `PNStatus` | A status object with additional information. |

#### PNHereNowResult

| Field | Type | Description |
| --- | --- | --- |
| `total_channels` | Int | Total `channels`. |
| `total_occupancy` | Int | Total `occupancy` |
| `channels` | Dictionary | A dictionary with values of [PNHereNowChannelData](#pnherenowchanneldata) for each channel. |

#### PNHereNowChannelData

| Field | Type | Description |
| --- | --- | --- |
| `channel_name` | String | `channel` name. |
| `occupancy` | Int | `occupancy` of the `channel`. |
| `occupants` | List | A list of [PNHereNowOccupantData](#pnherenowoccupantdata). |

#### PNHereNowOccupantData

| Field | Type | Description |
| --- | --- | --- |
| `uuid` | String | `uuid` of the user. |
| `state` | Dictionary | `state` of the user. |

### Other examples

#### Returning 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).
:::

```python
envelope = pubnub.here_now() \
    .channels("my_channel") \
    .include_uuids(True) \
    .include_state(True) \
    .sync()
```

##### Example response

```python
{
    total_channels: 1,
    channels: [{
        channel_name: "my_channel",
        occupancy: 1,
        occupants: [{
            uuid: "myUuid1"
            state: {
                "abcd": {
                    "age": 15
                }
            }
        }]
    }],
    total_occupancy: 1
}
```

#### Return occupancy only

:::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).
:::

You can return only the `occupancy` information for a single channel by specifying the channel and setting `UUIDs` to `False`:

```python
envelope = pubnub.here_now() \
    .channels("my_channel") \
    .include_uuids(False) \
    .include_state(False) \
    .sync()
```

##### Example response

```python
{
    total_channels: 1,
    channels: [{
        channel_name: "my_channel",
        occupancy: 3,
        occupants: []
    }],
    total_occupancy: 3
}
```

#### Here now for channel groups

```python
envelope = pubnub.here_now() \
    .channel_groups(['cg1', 'cg2', 'cg3']) \
    .include_uuids(True) \
    .include_state(True) \
    .sync()
```

##### Example response

```python
{
    total_channels: 1,
    channels: [
        {
            channel_name: "my_channel",
            occupancy: 1,
            occupants: [{
                uuid: "143r34f34t34fq34q34q3",
                state: None
            }]
        },
        {
            occupancy: 1,
            occupants: [{
                uuid: "123123234t234f34fq3dq",
                state: None
            }]
        },
        {
            occupancy: 1,
            occupants: [{
                uuid: "23f34d3f4rq34r34rq23q",
                state: None
            }]
        },
        {
            occupancy: 1,
            occupants: [{
                uuid: "w34tcw45t45tcw435tww3",
                state: None
            }]
        }
    ],
    total_occupancy: 4
}
```

#### Paginate through occupants

:::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).
:::

You can paginate through large occupant lists using `limit` and `offset`:

```python
# Get first 10 occupants
envelope = pubnub.here_now() \
    .channels("my_channel") \
    .limit(10) \
    .sync()

# Get next 10 occupants (starting from position 10)
envelope = pubnub.here_now() \
    .channels("my_channel") \
    .limit(10) \
    .offset(10) \
    .sync()
```

## Where now

:::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).
:::

This method returns the list of channels a UUID is subscribed to.

:::note Timeout events
If the app restarts (or the page refreshes) within the heartbeat window, no timeout event is generated.
:::

### Method(s)

To call `where_now()` you can use the following method(s) in the Python SDK:

```python
pubnub.where_now() \
    .uuid(String)
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: String | `uuid` to get info on. |

### Sample code

You simply need to define the `uuid` and the `callback` function to be used to send the data to as in the example below.

#### Get a list of channels a UUID is subscribed to

```python
envelope = pubnub.where_now().sync()
```

### Returns

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

| Field | Type | Description |
| --- | --- | --- |
| result | [PNWhereNowResult](#pnwherenowresult) | A detailed object containing the result of the operation. |
| status | `PNStatus` | A status object with additional information. |

#### PNWhereNowResult

| Field | Type | Description |
| --- | --- | --- |
| `channels` | List | The list of `channels` where the `UUID` is present. |

### Other examples

#### Obtain information about the current list of channels of some other UUID

##### Builder Pattern

```python
envelope = pubnub.where_now() \
    .uuid('some-other-uuid') \
    .sync()
```

##### Named Arguments

```python
envelope = pubnub.where_now(uuid='some-other-uuid').sync()
```

## User 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).
:::

Clients can set a dynamic custom state (score, game state, location) for their users on one or more channels and store it on a channel as long as the user stays subscribed.

The state is not persisted, and when the client disconnects, the state data is lost. For more information, refer to [Presence State](https://www.pubnub.com/docs/general/presence/presence-state).

:::note Presence state format
Presence state must be expressed as a `dict`. When calling `set_state`, be sure to supply an initialized `dict` which can be serialized.
:::

### Method(s)

#### Set state

```python
pubnub.set_state() \
    .channels(String|List|Tuple) \
    .channel_groups(String|List|Tuple) \
    .state(Dictionary)
```

| Parameter | Description |
| --- | --- |
| `channels`Type: String | List | Tuple | `channels` to set `state`. |
| `channel_groups`Type: String | List | Tuple | `channel groups` to set `state`. |
| `state`Type: Dictionary | `state` to set. |

#### Get state

```python
pubnub.get_state() \
    .channels(String|List|Tuple) \
    .channel_groups(String|List|Tuple) \
    .uuid(String)
```

| Parameter | Description |
| --- | --- |
| `channels`Type: String | List | Tuple | `channels` to get `state`. |
| `channel_groups`Type: String | List | Tuple | `channel groups` to get `state`. |
| `uuid`Type: String | `uuid` to get state from. |

### Sample code

#### Set state

##### Builder Pattern

```python
my_state = {
    'age': 20
}
envelope = pubnub.set_state() \
    .channels(['ch1', 'ch2', 'ch3']) \
    .state(my_state) \
    .sync()
```

##### Named Arguments

```python
envelope = pubnub.set_state(channels=['ch1', 'ch2', 'ch3'], state={'age': 20}).sync()
```

#### Get state

##### Builder Pattern

```python
envelope = pubnub.get_state() \
    .channels(['ch1', 'ch2', 'ch3']) \
    .uuid('such_uuid') \
    .sync()
```

##### Named Arguments

```python
envelope = pubnub.get_state(channels=['ch1', 'ch2', 'ch3'], uuid='such_uuid').sync()
```

### Returns

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

| Field | Type | Description |
| --- | --- | --- |
| result | [PNSetStateResult](#pnsetstateresult) | A detailed object containing the result of the operation. |
| status | `PNStatus` | A status object with additional information. |

#### PNSetStateResult

| Field | Type | Description |
| --- | --- | --- |
| `state` | Dictionary | Dictionary of UUIDs and the user states. |

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

| Field | Type | Description |
| --- | --- | --- |
| result | [PNGetStateResult](#pngetstateresult) | A detailed object containing the result of the operation. |
| status | `PNStatus` | A status object with additional information. |

#### PNGetStateResult

| Field | Type | Description |
| --- | --- | --- |
| `channels` | Dictionary | Dictionary of `channels` and the user states. |

### Other examples

#### Set state for channels in channel group

##### Builder Pattern

```python
my_state = {
    'age': 20
}
envelope = pubnub.set_state() \
    .channel_groups(['gr1', 'gr2', 'gr3']) \
    .state(my_state) \
    .sync()
```

##### Named Arguments

```python
envelope = pubnub.set_state(channel_groups=['gr1', 'gr2', 'gr3'], state={'age': 20}).sync()
```

The above code would return the following response to the client:

```python
{
    first  : "Robert",
    last   : "Plant",
    age    : 59,
    region : "UK"
}
```