---
source_url: https://www.pubnub.com/docs/sdks/go/api-reference/presence
title: Presence API for Go SDK
updated_at: 2026-05-22T11:06:35.890Z
sdk_name: PubNub Go SDK
sdk_version: v8.1.0
---

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

PubNub Go SDK, use the latest version: v8.1.0

Install:

```bash
go get github.com/pubnub/go/v8@v8.1.0
```

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 Go SDK:

```go
pn.HereNow().
    Channels([]string).
    ChannelGroups([]string).
    IncludeState(bool).
    IncludeUUIDs(bool).
    Limit(int).
    Offset(int).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Channels | []string | Optional |  | The `Channels` to get the here now details. |
| ChannelGroups | []string | Optional |  | The `Channel groups` to get the here now details. Wildcards are not supported. |
| IncludeState | bool | Optional | `false` | If `true`, the response will include the presence states of the users for `channels`/`channelGroups`. |
| IncludeUUIDs | bool | 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`. Use `0` to get occupancy counts without user details. |
| Offset | int | Optional | `0` | 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. This parameter is only included in the request when `Offset > 0`. |
| QueryParam | map[string]string | Optional | `nil` | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

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

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

import (
	"fmt"

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

// Example_hereNow demonstrates getting presence information for a channel
func Example_hereNow() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get presence information for a channel
	response, status, err := pn.HereNow().
		Channels([]string{"my-channel"}).
		IncludeUUIDs(true).  // Include list of UUIDs
		IncludeState(false). // Don't include state information
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("HereNow request successful")
		// Print occupancy for each channel
		for _, channelData := range response.Channels {
			fmt.Printf("Channel: %s, Occupancy: %d\n", channelData.ChannelName, channelData.Occupancy)
		}
	}

	// Output:
	// HereNow request successful
	// Channel: my-channel, Occupancy: 0
}
```

### Rest response from server

The `HereNow()` operation returns a. `PNHereNowResult` which contains the following fields:

| Method | Description |
| --- | --- |
| `TotalChannels`Type: int | Total `Channels` |
| `TotalOccupancy`Type: int | Total `Occupancy` |
| `Channels`Type: []HereNowChannelData |  |

#### HereNowChannelData

| Method | Description |
| --- | --- |
| `ChannelName`Type: string | `Channel` name |
| `Occupancy`Type: int | `Occupancy` of the `Channel` |
| `Occupants`Type: []HereNowOccupantsData |  |

#### HereNowOccupantsData

| Method | Description |
| --- | --- |
| `UUID`Type: string | `UUID` of the user |
| `State`Type: map[string]interface | `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).
:::

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

import (
	"fmt"

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

// Example_hereNowWithState demonstrates getting presence with state information
func Example_hereNowWithState() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get presence information including user state
	_, status, err := pn.HereNow().
		Channels([]string{"my-channel"}).
		IncludeUUIDs(true). // Include list of UUIDs
		IncludeState(true). // Include state information
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("HereNow with state successful")
	}

	// Output:
	// HereNow with state successful
}
```

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

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

import (
	"fmt"

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

// Example_hereNowOccupancyOnly demonstrates getting only occupancy count
func Example_hereNowOccupancyOnly() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get only occupancy count (no UUIDs or state)
	response, status, err := pn.HereNow().
		Channels([]string{"my-channel-100"}).
		IncludeUUIDs(false). // Don't include UUIDs
		IncludeState(false). // Don't include state
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Occupancy count retrieved")
		for _, channelData := range response.Channels {
			fmt.Printf("Occupancy: %d\n", channelData.Occupancy)
		}
	}

	// Output:
	// Occupancy count retrieved
	// Occupancy: 0
}
```

#### Here now for channel groups

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

import (
	"fmt"

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

// Example_hereNowChannelGroup demonstrates getting presence for channel groups
func Example_hereNowChannelGroup() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get presence for channel groups
	response, status, err := pn.HereNow().
		ChannelGroups([]string{"my-channel-group"}).
		IncludeUUIDs(true).
		IncludeState(false).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Channel group HereNow successful")
		fmt.Printf("Total occupancy: %d\n", response.TotalOccupancy)
	}

	// Output:
	// Channel group HereNow successful
	// Total occupancy: 0
}
```

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

```go
pn.WhereNow().
    UUID(string).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `UUID`Type: stringDefault: n/a | `UUID` to get info on. |
| `QueryParam`Type: map[string]stringDefault: `nil` | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

### Sample code

You simply need to define the `UUID` to be used to send the data to as in the example below.

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

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

import (
	"fmt"

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

// Example_whereNow demonstrates getting channels a UUID is subscribed to
func Example_whereNow() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get list of channels a specific UUID is subscribed to
	response, status, err := pn.WhereNow().
		UUID("some-user-uuid").
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("WhereNow request successful")
		fmt.Printf("Channels: %v\n", response.Channels)
	}

	// Output:
	// WhereNow request successful
	// Channels: []
}
```

### Rest response from server

| Method | Description |
| --- | --- |
| `Channels`Type: []string | The list of `channels` where the `UUID` is present. |

### Other examples

In the case you omit `UUID` field in `WhereNow()` request, the `UUID` of a current PubNub instance will be used.

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

import (
	"fmt"

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

// Example_whereNowCurrentUser demonstrates getting channels for current user
func Example_whereNowCurrentUser() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get channels for current user (omit UUID parameter)
	_, status, err := pn.WhereNow().
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("WhereNow for current user successful")
	}

	// Output:
	// WhereNow for current user successful
}
```

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

### Method(s)

#### Set state

```go
pn.SetState().
    Channels([]string).
    ChannelGroups([]string).
    State(map[string]interface{}).
    UUID(string).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: []string | `channels` to set `state`. |
| `ChannelGroups`Type: []string | `channel groups` to set `state`. |
| `State`Type: map[string]interface | `state` to set. |
| `UUID`Type: string | Set the Presence state info for a given `UUID`. |
| `QueryParam`Type: map[string]string | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

#### Get state

```go
pn.GetState().
    Channels([]string).
    ChannelGroups([]string).
    UUID(string).
    QueryParam(queryParam).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: []string | `channels` to get `state`. |
| `ChannelGroups`Type: []string | `channel groups` to get `state`. |
| `UUID`Type: string | Get the Presence state info for a given `UUID`. |
| `QueryParam`Type: map[string]string | QueryParam accepts a map, the keys and values of the map are passed as the query string parameters of the URL called by the API. |

### Sample code

#### Set state

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

import (
	"fmt"

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

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

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	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
}
```

#### Get state

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

import (
	"fmt"

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

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

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	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
}
```

### Response

The `SetState()` operation returns a `PNSetStateResult` which contains the following fields:

| Method | Description |
| --- | --- |
| `State`Type: interface | map of `UUIDs` and the user states. |

The `GetState()` operation returns a `PNGetStateResult` which contains the following fields:

| Method | Description |
| --- | --- |
| `State`Type: map[string]interface | map of `UUIDs` and the user states. |

### Other examples

#### Set state for channels in a channel group

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

import (
	"fmt"

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

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

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Set state for channel groups
	state := map[string]interface{}{
		"role": "moderator",
		"age":  25,
	}

	pn.SetState().
		ChannelGroups([]string{"my-channel-group"}).
		State(state).
		Execute()

	fmt.Println("SetState called for channel group")

	// Output:
	// SetState called for channel group
}
```

#### Get state for multiple channels

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

import (
	"fmt"

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

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

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Get state from multiple channels
	_, status, err := pn.GetState().
		Channels([]string{"channel-1", "channel-2"}).
		UUID("some-user-uuid").
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("State retrieved from multiple channels")
	}

	// Output:
	// State retrieved from multiple channels
}
```

## Heartbeat without subscription

:::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 send presence heartbeat notifications without subscribing to a channel. These notifications are sent periodically and indicate whether a client is connected or not. Make sure to correctly set the presence timeout and interval properties during [Configuration](https://www.pubnub.com/docs/sdks/go/api-reference/configuration) This feature requires the Presence add-on.

### Method(s)

To send heartbeat notifications without subscribing to a channel, you can use the following method(s) in the Go SDK:

```go
pn.Presence().
    Connected(bool).
    Channels([]‌string).
    ChannelGroups([]string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Connected` *Type: bool | Whether client's presence should be changed to connected (`true` to join) or off-line (`false` to leave). |
| `Channels`Type: []string | List of channel names for which client's presence state should be changed according to passed connected value. |
| `ChannelGroups`Type: []string | List of channel groups names for which client's presence state should be changed according to passed connected value. |

### Sample code

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

import (
	"fmt"

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

// Example_heartbeatJoin demonstrates sending heartbeat to join presence
func Example_heartbeatJoin() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Start heartbeating on channels without subscribing
	pn.Presence().
		Connected(true). // true = join presence
		Channels([]string{"my-channel"}).
		Execute()

	fmt.Println("Heartbeat started")

	// Output:
	// Heartbeat started
}
```

### Other examples

#### To stop heartbeating without subscription to channel or channel group

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

import (
	"fmt"

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

// Example_heartbeatLeave demonstrates stopping heartbeat to leave presence
func Example_heartbeatLeave() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Stop heartbeating on channels (leave presence)
	pn.Presence().
		Connected(false). // false = leave presence
		Channels([]string{"my-channel"}).
		Execute()

	fmt.Println("Heartbeat stopped")

	// Output:
	// Heartbeat stopped
}
```