---
source_url: https://www.pubnub.com/docs/presence/set-and-get-presence-state
title: Set and get presence state
updated_at: 2026-09-30T07:20:08.000Z
---

# Set and get presence state

> For AI agents: documentation index at https://www.pubnub.com/llms-full.txt

This guide shows you how to attach custom [presence state](https://www.pubnub.com/docs/presence/overview.md#attach-state-to-a-subscription) to a [User ID](https://www.pubnub.com/docs/architecture/core-concepts.md#user-id) on a channel, and how to read it back. Presence must be enabled on the keyset, and new keysets have it enabled by default. Presence state is custom data such as a mood, a game score, or a typing indicator. It exists only while the User ID stays subscribed to that channel. PubNub doesn't persist it, and disconnecting clears it. For anything that needs to survive a disconnect, use [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md) instead.

When [Access Manager](https://www.pubnub.com/docs/security/access-control/overview.md) is enabled, `Get State` and `Set State` both require `read` permission on the channel.

## Set state, then read it back

Call `Set State` with the User ID's current channel and a state object. By default, the state applies to the current client's own User ID. `Get State` then reads it back for any User ID, not just your own, which is how other clients learn about it outside of a [state-change event](https://www.pubnub.com/docs/presence/presence-events.md).

### JavaScript

```javascript
try {
  const response = await pubnub.setState({
    state: { status: 'online' },
    channels: ['ch1'],
    channelGroups: ['cg1'],
  });
  console.log('State set successfully:', response);
} catch (error) {
  console.error(`State set failed: ${error}`);
}
try {
  const response = await pubnub.getState({
    uuid: 'uuid',
    channels: ['ch1'],
    channelGroups: ['cg1'],
  });
  console.log('State retrieved successfully:', response);
} catch (error) {
  console.error(`State retrieval failed: ${error}`);
}
```

### Python

```python
my_state = {"mood": "pumped", "isTyping": False}

set_envelope = pubnub.set_state() \
    .channels(["chats.room1"]) \
    .state(my_state) \
    .sync()

get_envelope = pubnub.get_state() \
    .channels(["chats.room1"]) \
    .uuid("anotherUserId") \
    .sync()
```

### Java

```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 */ });
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 */ });
```

### Kotlin

```kotlin
pubnub.setPresenceState(
    channels = listOf("my_channel"),
    state = mapOf("is_typing" to "true")
    // if no uuid supplied, own is used
).async { result -> }
pubnub.getPresenceState(
    channels = listOf("ch1", "ch2", "ch3"), // channels to fetch state for
    uuid = "such_uuid" // uuid of user to fetch, or own uuid by default
).async { result -> }
```

### C#

```csharp
using PubnubApi;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
Dictionary<string, object> myState = new Dictionary<string, object>();
myState.Add("age", 20);

PNResult<PNSetStateResult> setstateResponse = await pubnub.SetPresenceState()
    .Channels(new string[] {
        "ch1",
        "ch2",
        "ch3"
    })
    .State(myState)
    .ExecuteAsync();

PNSetStateResult setstateResult = setstateResponse.Result;
PNStatus status = setstateResponse.Status;
// handle set state response
PNResult<PNGetStateResult> getstateResponse = await pubnub.GetPresenceState()
    .Channels(new string[] {
        // channels to fetch state for
        "ch1",
        "ch2",
        "ch3"
    })
    .ChannelGroups(new string[] {
        // channel groups to fetch state for
        "cg1",
        "cg2",
        "cg3"
    })
    .Uuid("suchUUID") // uuid of user to fetch, or for own uuid
    .ExecuteAsync();

PNGetStateResult getstateResult = getstateResponse.Result;
PNStatus status = getstateResponse.Status;
// handle response
```

### Go

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v10"
)

// Example_setState demonstrates setting user state on channels
func Example_setState() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Set custom state for user on channel
	state := map[string]interface{}{
		"is_typing": true,
		"mood":      "happy",
		"status":    "online",
	}

	_, status, err := pn.SetState().
		Channels([]string{"my-channel"}).
		State(state).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 {
		fmt.Println("State set successfully")
	}

	// Output:
	// State set successfully
}

// Example_getState demonstrates retrieving user state from channels
func Example_getState() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Get state for specific user on channels
	_, status, err := pn.GetState().
		Channels([]string{"my-channel"}).
		UUID("some-user-uuid").
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 {
		fmt.Println("State retrieved successfully")
	}

	// Output:
	// State retrieved successfully
}
```

### Swift

```swift
// Set the presence state for a channel and channel group
pubnub.setPresence(
  state: ["new": "state"],
  on: ["channelSwift"],
  and: ["demo"]
) { result in
  switch result {
  case let .success(presenceSet):
    print("The presence State set as a `JSONCodable`: \(presenceSet)")
  case let .failure(error):
    print("Failed Set State Response: \(error.localizedDescription)")
  }
}
// Get the presence state for a channel and channel group
pubnub.getPresenceState(
  for: pubnub.configuration.uuid,
  on: ["channelSwift"],
  and: ["demo"]
) { result in
  switch result {
  case let .success(uuid, stateByChannel):
    print("The UUID `\(uuid)` has the following presence state \(stateByChannel)")
  case let .failure(error):
    print("Failed Get State Response: \(error.localizedDescription)")
  }
}
```

Most other SDKs document the same two calls in the Presence section of their API reference, for example [PHP](https://www.pubnub.com/docs/sdks/php/api-reference/presence.md#user-state) or [Ruby](https://www.pubnub.com/docs/sdks/ruby/api-reference/presence.md#user-state).

Setting state overwrites the User ID's entire existing state on that channel. To change one field and keep the rest, send the full state object back, not just the field that changed. Keep the payload small, because state travels on every `Here Now` response and every `state-change` event that carries it.

## Set state for a channel group

Pass a channel group instead of, or alongside, a channel list to apply the same state to every channel in the group in one call.

### C#

```csharp
using PubnubApi;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
Dictionary<string, object> myState = new Dictionary<string, object>();
myState.Add("age", 20);

PNResult<PNSetStateResult> setstateResponse = await pubnub.SetPresenceState()
    .ChannelGroups(new string[] {
        // apply on those channel groups
        "cg1",
        "cg2",
        "cg3"
    })
    .Channels(new string[] {
        // apply on those channels
        "ch1",
        "ch2",
        "ch3"
    })
    .State(myState) // the new state
    .ExecuteAsync();

PNSetStateResult setstateResult = setstateResponse.Result;
PNStatus status = setstateResponse.Status;
// on new state for those channels
```

### Kotlin

```kotlin
pubnub.setPresenceState(
    channels = listOf("ch1", "ch2", "ch3"), // apply on those channels
    channelGroups = listOf("cg1", "cg2", "cg3"), // apply on those channel groups
    state = JsonObject().apply { addProperty("is_typing", true) }
).async { result ->
    result.onSuccess { res ->
        res.state // {"data":{"is_typing":true}}
    }.onFailure { e ->
        // handle error
        e.message
        e.statusCode
        e.pubnubError
    }
}
```

## Related tasks

* [Receive presence events](https://www.pubnub.com/docs/presence/receive-presence-events.md). Get the `state-change` event that fires when a state you set changes.
* [Get online users in a channel](https://www.pubnub.com/docs/presence/get-online-users-in-channel.md). Fetch every occupant's state in one `Here Now` call instead of one `Get State` call per User ID.
* [Presence](https://www.pubnub.com/docs/presence/overview.md). How presence state relates to occupancy, events, and membership.
* [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md). Store structured metadata that needs to survive a disconnect.

Last updated at: 2026-09-30T07:20:08.000Z
