---
source_url: https://www.pubnub.com/docs/general/presence/overview
title: Presence Basics
updated_at: 2026-05-25T11:26:29.902Z
---

> 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 Basics

Presence gives you visibility into who is currently subscribed to a channel.

Presence monitors channel subscribers and delivers real-time status information. You can:

* Measure channel occupancy.
* Monitor and add dynamic custom state information, like profile info, typing indicators, or current location.
* Use [Events & Actions](https://www.pubnub.com/docs/serverless/events-and-actions/events#webhooks) to have PubNub notify your server whenever presence events occur.

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

###### Understand how User IDs drive presence tracking

Presence identifies subscribers by their [User ID](https://www.pubnub.com/docs/general/setup/users-and-devices). Each presence event (join, leave, timeout, state-change) includes the User ID of the affected client. If multiple devices connect with the same User ID, they appear as one subscriber for billing but may produce rapid leave/join sequences when individual devices disconnect. See [Users & Devices](https://www.pubnub.com/docs/general/setup/users-and-devices#device-level-presence-tracking) for strategies to handle multi-device scenarios.

When you enable Presence on a keyset in the [Admin Portal](https://admin.pubnub.com), you can subscribe to presence events. PubNub automatically creates presence equivalents of all channels. Presence channels reuse the base channel name with the `-pnpres` suffix and track all presence events about users.

###### Extend your event listeners with presence

Because presence events flow through `-pnpres` channels using the same delivery model as messages, you receive them with the same [event listener](https://www.pubnub.com/docs/general/messages/receive#add-an-event-handler) you already use for messages and signals. For details on event types, payloads, and subscribe options, see [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events).

:::note Subscription with Presence
To receive Presence events, you [subscribe with Presence](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#subscribe) and have Presence enabled on your keyset. Make sure you configure Presence to track [Presence-related events](https://www.pubnub.com/docs/general/presence/overview#configuration) for all or selected channels (through [Presence Management rules](https://www.pubnub.com/docs/bizops-workspace/presence-management)).
:::

##### Ready for your weekly check-in?

I’m Edward, and I work as an engineering lead at a UX-focused company that delivers a personalized platform for one-on-one meetings (also known as check-ins or 1:1s). At work, I’m responsible for what they call “resource management” i.e. utilizing limited engineers’ time wisely to produce the most optimal output. Recently, I’ve had a chance to prove myself yet again when finding messaging support for our product. I figured that we needed to find an external real-time solution that could support us, given that we wanted to concentrate to the fullest on creating the UI differentiation for our platform. We couldn’t handle these real-time functionalities in-house and focus on UI simultaneously to ensure good product quality.

The goal was clear: we need a reliable messaging infrastructure that is fast, scalable and offers chat-like features, including near-instant communication, knowing who is currently online, and reacting to messages. We required a stable backend that we could beautify to produce a unique and personalized UI/UX experience for our customers. We came across PubNub and it had everything we needed: [Pub/Sub API](https://www.pubnub.com/docs/general/messages/publish) for messaging, [Presence API](https://www.pubnub.com/docs/general/messages/publish) for users’ status visibility, and [Message Actions API](https://www.pubnub.com/docs/general/messages/actions) for expressing sentiments with emojis. Now that we had all the building blocks in one place, we could concentrate on what we’re best at - creating an engaging UI offering.

You cannot imagine what a good decision it was to rely on PubNub's infrastructure. We focused solely on good UX, and our decision already bears fruit. We receive positive feedback from our customers who like our sleek UI backed by real-time functionalities that enhance their experience in 1:1s. Who would’ve thought that good engineering decisions could turn assessment meetings with managers into a fun & anticipated activity?

## Configuration

To use Presence, enable and configure it on a selected app keyset in the [Admin Portal](https://admin.pubnub.com/).

:::tip Public Admin Portal demo
Want to browse through the Admin Portal without creating an account? Explore it through the [Public Demo](https://demo-admin.pubnub.com/) that shows examples of most PubNub features for transport and logistics use case.
:::

When you create a keyset in the [Admin Portal](https://admin.pubnub.com/), [Presence](https://www.pubnub.com/docs/general/presence/overview) is enabled by default.

Choose how you want to configure Presence:

* Selected channels only (recommended) — disable Presence events by default. You selectively enable Presence for specific channels using rules in Presence Management. Until then, you will not receive Presence-related events such as join, leave, or presence state changes.
* All channels — track Presence-related events for every channel (may increase cost).

![Presence events list in Presence Management UI showing event type filters](https://www.pubnub.com/assets/images/presence-events-5b07a283349cb547573735543ecf1a65.png)

Presence offers the following options:

![Presence configuration options in Admin Portal: Announce Max, Interval, Deltas, TCP detection, Filtering, Active Notice Channel, Debounce](https://www.pubnub.com/assets/images/presence-f9884dbf008cdd44f39e97d0436c8dc1.png)

| Option | Description |
| --- | --- |
| **Announce Max** | The maximum channel occupancy above which specific events are reduced. When occupancy exceeds this value, `join`, `leave`, and `timeout` [Presence events](https://www.pubnub.com/docs/general/presence/presence-events#presence-event-types) are replaced by recurring `interval` events that report channel occupancy. |
| **Interval** | The cadence (in seconds) for `interval` events when Announce Max is exceeded. |
| **Presence Deltas** | Adds two fields to each `interval` event: lists of users who joined and who left since the last update. |
| **Generate Leave on TCP FIN or RST** | Detects network-layer connection termination and reports a `leave` event instead of a `timeout` event (for example, when a browser tab closes or an app is force quit). Does not generate additional billable events. If the client also sends an explicit unsubscribe before the connection drops, duplicate leave events are not generated. Explicit SDK unsubscribes are generally more reliable. |
| **Stream Filtering** | Filters Presence events at the client. You receive only relevant events on the Presence channel (for example, `join` events for a specific User ID). |
| **Active Notice Channel** | Sends notifications when a channel switches between active (has subscribers) and inactive (no subscribers). |
| **Debounce** | The number of seconds to wait before allowing a `join` event after an explicit `leave`. Helps smooth out rapid state changes. |

:::tip Best practice
For the most predictable presence behavior, use explicit SDK unsubscribes rather than relying solely on **Generate Leave on TCP FIN or RST**. When the SDK changes its channel subscriptions, it aborts the existing subscribe request; because this is indistinguishable from a lost connection at the network level, it can result in a `leave` followed by a `join` instead of a single clean transition.
:::

###### Secure presence queries with Access Manager

When Access Manager is enabled, `read` permission on a channel grants access to [HereNow](https://www.pubnub.com/docs/general/presence/overview#get-online-users-in-channel), [GetState, and SetState](https://www.pubnub.com/docs/general/presence/presence-state) for that channel. WhereNow requires no channel-level permission. Subscribing to presence events on `-pnpres` channels also requires `read`. See the [Presence permissions table](https://www.pubnub.com/docs/general/security/access-control#presence) for the full mapping.

## Get online users in channel

When a client opens the app, it's often required to discover what other users are already subscribed to that channel (for example, to construct a chat room's online friends list). You can obtain a list of client User IDs, including clients' state data, and the total occupancy of the channel using the Here Now API.

Once the current state has been fetched, your app can rely on presence events to keep the user state up to date. Go to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events) to learn more.

###### Extend presence with persistent membership data

Presence shows who is currently subscribed, but cannot show offline members. [Membership metadata](https://www.pubnub.com/docs/general/metadata/membership-metadata) provides the persistent record of which users belong to a channel regardless of their online state. Combine a HereNow query for live occupancy with a membership list to render a complete roster that distinguishes online members from offline ones.

:::note Cache response time
The `hereNow()` method has a 3-second response cache time.
:::

:::note Wildcard patterns and channel groups
Wildcard channel patterns (such as `sports.*`) are a subscribe-only concept and are not supported with `hereNow`. To query occupancy across a group of related channels, pass a channel group name instead. `hereNow` supports a single channel, multiple channels, or a channel group.
:::

:::note Channels excluded from Presence Management
If you exclude a channel from Presence tracking via [Presence Management](https://www.pubnub.com/docs/bizops-workspace/presence-management) rules, `hereNow()` returns zero occupancy and an empty user list (like a channel with no active subscribers), not an error.
:::

###### JavaScript

```javascript
pubnub.hereNow(
  {
    channels: ["chats.room1", "chats.room2"],
    includeState: true
  },
  function (status, response) {
    console.log(status, response);
  }
);
```

###### Swift

```swift
pubnub.hereNow(on: ["chats.room1", "chats.room2"]), and: [],
  includeUUIDs: true, also: true { result in
    switch result {
      case let .success(response):
        print("Successful hereNow Response: \(response)")

      case let .failure(error):
        print("Failed hereNow Response: \(error.localizedDescription)")
    }
})
```

###### Objective-C

```objectivec
[self.pubnub hereNowForChannel: @[@"chats.room1", "chats.room2"]
    withVerbosity:PNHereNowState
    completion:^(PNPresenceChannelHereNowResult *result, PNErrorStatus *status) {
  // parse the HereNow result parameter
}];
```

###### Java

```java
pubnub.hereNow()
  .channels(Arrays.asList("chats.room1", "chats.room2"))
  .includeState(true)
  .async(result -> {
      result.onSuccess(res -> {
          for (PNHereNowChannelData channelData : res.getChannels().values()) {
              System.out.println("---");
              System.out.println("channel:" + channelData.getChannelName());
              System.out.println("occupancy: " + channelData.getOccupancy());
              System.out.println("occupants:");

              for (PNHereNowOccupantData occupant : channelData.getOccupants()) {
                  System.out.println("userId: " + occupant.getUuid()
                          + " state: " + occupant.getState());
              }
          }
      }).onFailure(exception -> {
          exception.printStackTrace();
      });
  });
```

###### C#

```csharp
pubnub.HereNow()
  .Channels(new string[] {"chats.room1", "chats.room2"})
  .IncludeState(true)
  .Execute(new PNHereNowResultEx((result, status) => {
    if (status.Error) {
      Console.WriteLine("HereNow error: " + status);
    }
    else if (result.Channels != null && result.Channels.Count > 0) {
      foreach (KeyValuePair<string, PNHereNowChannelData> kvp in result.Channels) {
        PNHereNowChannelData channelData = kvp.Value;
        Console.WriteLine("---");
        Console.WriteLine("channel:" + channelData.ChannelName);
        Console.WriteLine("occupancy:" + channelData.Occupancy);
        Console.WriteLine("Occupants:");

        if (channelData.Occupants != null && channelData.Occupants.Count > 0) {
          for (int index = 0; index < channelData.Occupants.Count; index++) {
            PNHereNowOccupantData occupant = channelData.Occupants[index];
            Console.WriteLine(string.Format("UserId: {0}", occupant.UserId));
            Console.WriteLine(string.Format("state:{1}", (occupant.State != null) ?
            pubnub.JsonPluggableLibrary.SerializeToJsonString(occupant.State) : ""));
          }
        }
      }
    }
  }
));
```

###### Python

```python
def here_now_callback(result, status):
  if status.is_error():
    print("here_now error: %s" % status)
    return

  for channel_data in result.channels:
    print("---")
    print("channel: %s" % channel_data.channel_name)
    print("occupancy: %s" % channel_data.occupancy)

    print("occupants: %s" % channel_data.channel_name)

    for occupant in channel_data.occupants:
      print("user_id: %s, state: %s" % (occupant.user_id, occupant.state))

pubnub.here_now()\
  .channels("chats.room1", "chats.room2")\
  .include_state(True)\
  .pn_async(here_now_callback)
```

:::tip Custom user state
You can add custom state information to the users in your application. For more details, refer to [Presence State](https://www.pubnub.com/docs/general/presence/presence-state).
:::

## Get subscribed channels for user

Sometimes it may be necessary for the client app to confirm the channels to which it's currently subscribed. Though this is rarely necessary to do this, except for possibly when you're testing and troubleshooting your app. This can be accomplished with the *Where Now* API.

### JavaScript

```javascript
pubnub.whereNow({uuid: pubnub.uuid},
  function (status, response) {
    // handle status, response
  }
);
```

### Swift

```swift
pubnub.whereNow(for: pubnub.uuid) { result in
  switch result {
  case let .success(response):
    print("Successful WhereNow Response: \(response)")

  case let .failure(error):
    print("Failed WhereNow Response: \(error.localizedDescription)")
  }
}
```

### Objective-C

```objectivec
[self.pubnub whereNowUUID:self.pubnub.uuid withCompletion:
      ^(PNPresenceWhereNowResult *result, PNErrorStatus *status) {
  if (!status) {
    NSLog(status);
  }
  else {
    NSLog(result);
  }
}];
```

### Java

```java
pubnub.whereNow()
  .async(result -> { /* check result */ });
```

### C#

```csharp
pubnub.WhereNow()
  .Execute(new PNWhereNowResultExt((result, status) => {
    if (status.isError) {
      Console.WriteLine(status.ErrorData.Information);
    }
    else {
      Console.WriteLine(result);
    }
  }
));
```

### Python

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

###### Understand how channels support presence

Presence operates per channel. Each channel you subscribe to with presence enabled generates a dedicated `-pnpres` companion channel. You can organize channels into [channel groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) and receive aggregated presence events for all member channels through a single subscription, reducing the overhead of tracking many channels individually. Use consistent [channel naming conventions](https://www.pubnub.com/docs/general/channels/channel-naming) with dot-delimited prefixes to configure presence rules for channel patterns in [Presence Management](https://www.pubnub.com/docs/bizops-workspace/presence-management).

## Presence events

Now that you know how to fetch the current state, Presence events keep that state in sync. Presence events are sent as users come online or go offline. For details on event types and how to receive them in your client, see [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events).

## Terms in this document

* **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.
* **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.
