---
source_url: https://www.pubnub.com/docs/sdks/java/api-reference/presence
title: Presence API for Java SDK
updated_at: 2026-06-30T11:07:20.939Z
sdk_name: PubNub Java SDK
sdk_version: 6.4.5
---

> 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 Java SDK

PubNub Java SDK, use the latest version: 6.4.5

Install:

```bash
Add PubNub dependency to your build@6.4.5
```

:::warning Breaking changes in v9.0.0
PubNub Java SDK version 9.0.0 unifies the codebases for Java and [Kotlin](https://www.pubnub.com/docs/sdks/kotlin) SDKs, introduces a new way of instantiating the PubNub client, and changes asynchronous API callbacks and emitted [status events](https://www.pubnub.com/docs/sdks/java/status-events). These changes can impact applications built with previous versions (< `9.0.0`) of the Java SDK.
For more details about what has changed, refer to [Java/Kotlin SDK migration guide](https://www.pubnub.com/docs/sdks/kotlin/migration-guides/kotlin-v9-migration-guide).
:::

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

## 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 Java SDK:

```java
this.pubnub.hereNow()
    .channels(Array)
    .channelGroups(Arrays)
    .includeState(true)
    .includeUUIDs(true)
    .limit(int)
    .offset(Integer)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channels | Array | Optional |  | The `channels` to get the `here now` details. |
| channelGroups | Arrays | Optional |  | The `channelGroups` to get the `here now` details. Wildcards are not supported. |
| includeState | Boolean | Optional | `false` | If `true`, the response will include the presence states of the users for `channels`/`channelGroups` |
| includeUUIDs | Boolean | Optional | `true` | If `true`, the response will include the `UUIDs` of the connected clients. |
| limit | int | Optional | `1000` | Maximum number of occupants to return per channel. Valid range: `0-1000`. The server enforces the maximum of `1000` and rejects values outside this range. Use `0` to get occupancy counts without user details (when `limit=0`, the server omits UUIDs entirely). |
| offset | Integer | Optional | `null` | Zero-based starting index for pagination. Returns occupants starting from this position in the list. Must be `>= 0`. Requires `limit > 0`. Server rejects negative values. Use with `limit` to paginate through large occupant lists. |
| async | Consumer<Result> | Yes |  | `Consumer` of a `Result` of type `PNHereNowResult` |

### Sample code

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

#### Get a list of UUIDs subscribed to channel

```java
import com.pubnub.api.PubNubException;
import com.pubnub.api.UserId;
import com.pubnub.api.java.PubNub;
import com.pubnub.api.java.v2.PNConfiguration;
import com.pubnub.api.models.consumer.presence.PNHereNowChannelData;
import com.pubnub.api.models.consumer.presence.PNHereNowOccupantData;
import com.pubnub.api.models.consumer.presence.PNHereNowResult;

import java.util.Arrays;

public class HereNowApp {
    public static void main(String[] args) throws PubNubException {
        // Configure PubNub instance
        PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("demoUserId"), "demo");
        configBuilder.publishKey("demo");
        configBuilder.secure(true);

        PubNub pubnub = PubNub.create(configBuilder.build());

        // Get presence information for specified channels
        pubnub.hereNow()
                .channels(Arrays.asList("coolChannel", "coolChannel2"))
                .includeUUIDs(true)
                .limit(100)
                .offset(10)
                .async(result -> {
                    result.onSuccess((PNHereNowResult res) -> {

                        System.out.println("Total Channels: " + res.getTotalChannels());
                        System.out.println("Total Occupancy: " + res.getTotalOccupancy());

                        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("UUID: " + occupant.getUuid() + " State: " + occupant.getState());
                            }
                        }
                    }).onFailure( (PubNubException exception) -> {
                        System.out.println("Error retrieving hereNow data: " + exception.getMessage());
                    });
                });
    }
}
```

### Returns

The `hereNow()` operation returns a `PNHereNowResult` which contains the following operations:

| Method | Description |
| --- | --- |
| `getTotalChannels()`Type: Int | Total `Channels`. |
| `getTotalOccupancy()`Type: Int | Total `Occupancy`. |
| `getChannels()`Type: Map`<String, PNHereNowChannelData>` | A map with values of `PNHereNowChannelData` for each `channel`. See [PNHereNowChannelData](#pnherenowchanneldata) for more details. |

#### PNHereNowChannelData

| Method | Description |
| --- | --- |
| `getChannelName()`Type: String | `Channel` name. |
| `getOccupancy()`Type: Int | `Occupancy` of the `channel`. |
| `getOccupants()`Type: List`<PNHereNowOccupantData>` | A list of `PNHereNowOccupantData`, see [PNHereNowOccupantData](#pnherenowoccupantdata) for more details. |

#### PNHereNowOccupantData

| Method | Description |
| --- | --- |
| `getUuid()`Type: String | `UUIDs` of the user. |
| `getState()`Type: Object | `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).
:::

```java
pubNub.hereNow()
        .channels(Arrays.asList("my_channel")) // who is present on those channels?
        .includeState(true) // include state with request (false by default)
        .includeUUIDs(true) // if false, only shows occupancy count
        .async(result -> {
            result.onSuccess((PNHereNowResult res) -> {
                // Iterate through channels if the request was successful
                for (PNHereNowChannelData channelData : res.getChannels().values()) {
                    System.out.println("Channel: " + channelData.getChannelName());
                    System.out.println("Occupancy: " + channelData.getOccupancy());
                    System.out.println("Occupants:");
                    for (PNHereNowOccupantData occupant : channelData.getOccupants()) {
                        System.out.println("UUID: " + occupant.getUuid() + " State: " + occupant.getState());
                    }
                }
            }).onFailure((PubNubException exception) -> {
                // Handle errors if the request fails
                System.err.println("Error retrieving hereNow data: " + exception.getMessage());
                exception.getPubnubError();
                exception.getCause();
                exception.getStatusCode();
            });
        });
```

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

```java
pubNub.hereNow()
        .channels(Arrays.asList("my_channel")) // who is present on those channels?
        .includeState(false) // include state with request (false by default)
        .includeUUIDs(false) // if false, only shows occupancy count
        .async(result -> {
            result.onSuccess((PNHereNowResult res) -> {
                // Iterate through channels if the request was successful
                for (PNHereNowChannelData channelData : res.getChannels().values()) {
                    System.out.println("Channel: " + channelData.getChannelName()); // my_channel
                    System.out.println("Occupancy: " + channelData.getOccupancy()); // 3
                }
            }).onFailure((PubNubException exception) -> {
                // Handle errors if the request fails
                System.err.println("Error retrieving hereNow data: " + exception.getMessage());
                exception.getPubnubError();
                exception.getCause();
                exception.getStatusCode();
            });
        });
```

#### Here now for channel groups

```java
pubNub.hereNow()
        .channelGroups(Arrays.asList("cg1", "cg2", "cg3")) // who is present on channel groups?
        .includeState(true) // include state with request (false by default)
        .includeUUIDs(true) // if false, only shows occupancy count
        .async(result -> {
            result.onSuccess((PNHereNowResult res) -> {
                // Get total occupancy across all channels if the request was successful
                System.out.println("Total Occupancy: " + res.getTotalOccupancy()); // 12

                // Iterate through channels in the channel group
                for (PNHereNowChannelData channelData : res.getChannels().values()) {
                    System.out.println("Channel: " + channelData.getChannelName());
                    System.out.println("Occupancy: " + channelData.getOccupancy());
                    System.out.println("Occupants:");
                    for (PNHereNowOccupantData occupant : channelData.getOccupants()) {
                        System.out.println("UUID: " + occupant.getUuid() + " State: " + occupant.getState());
                    }
                }
            }).onFailure((PubNubException exception) -> {
                // Handle errors if the request fails
                System.err.println("Error retrieving hereNow data: " + exception.getMessage());
                exception.getPubnubError();
                exception.getCause();
                exception.getStatusCode();
            });
        });
```

## 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 `whereNow()` you can use the following method(s) in the Java SDK:

```java
pubnub.whereNow()
    .uuid(String)
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: String | `Uuid` of the user we want to spy on. |
| `async` *Type: Command | Execute as `async`. |

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

```java
pubNub.whereNow().async(result -> {
    result.onSuccess((PNWhereNowResult res) -> {
        System.out.println("User is currently subscribed to following channels: " + res.getChannels());
    }).onFailure((PubNubException exception) -> {
        // Handle errors if the request fails
        System.err.println("Error retrieving whereNow data: " + exception.getMessage());
        exception.getPubnubError();
        exception.getCause();
        exception.getStatusCode();
    });
});
```

### Returns

The `whereNow()` operation returns a `PNWhereNowResult` which contains the following operations:

| Method | Description |
| --- | --- |
| `getChannels()`Type: List`<String>` | The list of `channels` where the `UUID` is present. |

### Other examples

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

```java
pubNub.whereNow().uuid("some-other-uuid").async(result -> {
    result.onSuccess((PNWhereNowResult res) -> {
        System.out.println("some-other-uuid is currently subscribed to following channels: " + res.getChannels());
    }).onFailure((PubNubException exception) -> {
        // Handle errors if the request fails
        System.err.println("Error retrieving whereNow data: " + exception.getMessage());
        exception.getPubnubError();
        exception.getCause();
        exception.getStatusCode();
    });
});
```

## 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 JsonObject. When calling `setState`, be sure to supply an initialized JsonObject or POJO which can be serialized to a JsonObject.
:::

### Method(s)

#### Set state

```java
this.pubnub.setPresenceState()
    .channels(Array)
    .channelGroups(Array)
    .state(HashMap)
    .uuid(String)
```

| Parameter | Description |
| --- | --- |
| `channels`Type: Array | `Channels` to set `state`. |
| `channelGroups`Type: Array | `ChannelGroups` to set `state`. |
| `state`Type: HashMap | `State` to set. |
| `uuid`Type: String | Set `state` for specific `UUID`. |
| `async` *Type: `Consumer<Result>` | `Consumer` of a `Result` of type `PNSetStateResult`. |

#### Get state

```java
this.pubnub.getPresenceState()
    .channels(Arrays)
    .channelGroups(Arrays)
    .uuid(String)
```

| Parameter | Description |
| --- | --- |
| `channels`Type: Arrays | `Channel` name to fetch the `state`. |
| `channelGroups`Type: Arrays | `ChannelGroups` name to fetch the `state`. |
| `uuid`Type: String | `UUID` |
| `async` *Type: `Consumer<Result>` | `Consumer` of a `Result` of type `PNGetStateResult`. |

### Sample code

#### Set state

```java
String channel = "my_channel";
JsonObject state = new JsonObject();
state.addProperty("is_typing", true);

pubNub.setPresenceState()
        .channels(Arrays.asList(channel))
        .state(state)
        .async(result -> { /* check result */ });
```

#### Get state

```java
pubNub.getPresenceState()
        .channels(Arrays.asList("ch1", "ch2", "ch3")) // channels to fetch state for
        .channelGroups(Arrays.asList("cg1", "cg2", "cg3")) // channel groups to fetch state for
        .uuid("suchUUID") // uuid of user to fetch, or for own uuid
        .async(result -> { /* check result */ });
```

### Returns

The `setPresenceState()` operation returns a `PNSetStateResult` which contains the following operations:

| Method | Description |
| --- | --- |
| `getState()`Type: Map`<String, Object>` | Map of `UUIDs` and the user states. |

The `getPresenceState()` operation returns a `PNGetStateResult` which contains the following operations:

| Method | Description |
| --- | --- |
| `getStateByUUID()`Type: Map`<String, Object>` | Map of `UUIDs` and the user states. |

### Other examples

#### Set state for channels in channel group

```java
JsonObject state = new JsonObject();
state.addProperty("is_typing", true);

pubNub.setPresenceState()
        .channelGroups(Arrays.asList("cg1", "cg2", "cg3")) // apply on those channel groups
        .channels(Arrays.asList("ch1", "ch2", "ch3")) // apply on those channels
        .state(state) // the new state
        // snippet.hide
        // IntelliJ show error in .async(result -> { /* check result */ });
        // but it compiles fine. In pure project with Java SDK as dependency error is not present
        // snippet.show
        .async(result -> { /* check result */ });
```

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

```java
Channel channel = pubNub.channel("ch1");
Subscription subscription = channel.subscription(SubscriptionOptions.receivePresenceEvents());

subscription.setOnPresence(pnPresenceEventResult -> {
    if (pnPresenceEventResult.getEvent().equals("state-change")) {
        boolean is_typing = pnPresenceEventResult.getState()
                // snippet.hide
                    // getAsJsonObject is displayed as having issue but it compiles fine. In pure project with Java SDK as dependency error is not present
                // snippet.show
                .getAsJsonObject()
                .get("is_typing")
                .getAsBoolean();
    }
});
```