---
source_url: https://www.pubnub.com/docs/sdks/c-sharp/api-reference/presence
title: Presence API for C# SDK
updated_at: 2026-06-17T11:38:53.483Z
sdk_name: PubNub C# SDK
sdk_version: 8.3.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 C# SDK

PubNub C# SDK, use the latest version: 8.3.0

Install:

```bash
dotnet add package PubNub@8.3.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).

:::tip Request execution
Use `try`/`catch` when working with the C# SDK.
If a request has invalid parameters (for example, a missing required field), the SDK throws an exception. If the request reaches the server but fails (server error or network issue), the error details are available in the returned `status`.
```csharp
try
{
    PNResult<PNPublishResult> publishResponse = await pubnub.Publish()
        .Message("Why do Java developers wear glasses? Because they can't C#.")
        .Channel("my_channel")
        .ExecuteAsync();
    PNStatus status = publishResponse.Status;
    Console.WriteLine("Server status code : " + status.StatusCode.ToString());
}
catch (Exception ex)
{
    Console.WriteLine($"Request can't be executed due to error: {ex.Message}");
}
```
:::

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

```csharp
pubnub.HereNow()
        .Channels(Array)
        .ChannelGroups(Array)
        .IncludeState(bool)
        .IncludeUUIDs(bool)
        .Limit(int)
        .Offset(int)
        .QueryParam(Dictionary<string,object>)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Channels | Array | Optional |  | The `Channels` to get the `here now` details. |
| ChannelGroups | Array | Optional |  | The `ChannelGroups` to get the `here now` details. Wildcards are not supported. |
| IncludeState | bool | Optional |  | If `true`, the response will include the presence states of the users for `Channels`/`ChannelGroups`. |
| IncludeUUIDs | bool | Optional |  | 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. **Note:** This parameter is only applied when specific `Channels` are provided. |
| 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. **Note:** This parameter is only applied when specific `Channels` are provided and only included in the request when `Offset > 0`. |
| QueryParam | Dictionary<string, | Optional |  | Dictionary `object` to pass name/value pairs as query `string` params with PubNub URL request for debug purpose. |
| Async | PNCallback | Optional |  | PNCallback of type PNHereNowResult. This parameter is deprecated and will be removed in a future version. Please use the `ExecuteAsync` parameter instead. |
| Execute | PNCallback | Yes |  | `PNCallback` of type `PNHereNowResult`. |
| ExecuteAsync | None | Optional |  | Returns `PNResult<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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
try
{
    PNResult<PNHereNowResult> herenowResponse = await pubnub.HereNow()
        .Channels(new string[] { "coolChannel", "coolChannel2" })
        .IncludeUUIDs(true)
        .ExecuteAsync();

    PNHereNowResult herenowResult = herenowResponse.Result;
    PNStatus status = herenowResponse.Status;

    if (!status.Error && herenowResult != null)
    {
        foreach (KeyValuePair<string, PNHereNowChannelData> channelData in herenowResult.Channels)
        {
            Console.WriteLine("---");
            Console.WriteLine("Channel: " + channelData.Value.ChannelName);
            Console.WriteLine("Occupancy: " + channelData.Value.Occupancy);

            if (channelData.Value.Occupants != null)
            {
                foreach (var occupant in channelData.Value.Occupants)
                {
                    Console.WriteLine($"UUID: {occupant.Uuid}");
                    Console.WriteLine($"State: {(occupant.State != null ? pubnub.JsonPluggableLibrary.SerializeToJsonString(occupant.State) : "No state")}");
                }
            }
        }
    }
    else
    {
        Console.WriteLine("Error occurred: " + pubnub.JsonPluggableLibrary.SerializeToJsonString(status));
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Request cannot be executed due to error: {ex.Message}");
}
```

### Returns

The `HereNow()` operation returns a `PNResult<PNHereNowResult>` which contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `Result` | PNHereNowResult | Returns a `PNHereNowResult` object. |
| `Status` | PNStatus | Returns a `PNStatus` object. |

`PNHereNowResult` contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `TotalChannels` | int | Total `Channels`. |
| `TotalOccupancy` | int | Total `Occupancy`. |
| `Channels` | `Dictionary<string, PNHereNowChannelData>` | A map with values of `PNHereNowChannelData` for each `channel`. See [PNHereNowChannelData](#pnherenowchanneldata) for more details. |

#### PNHereNowChannelData

| Property Name | Type | Description |
| --- | --- | --- |
| `ChannelName` | string | `Channel` name. |
| `Occupancy` | int | `Occupancy` of the `channel`. |
| `Occupants` | List`<PNHereNowOccupantData>` | A list of `PNHereNowOccupantData`, see [PNHereNowOccupantData](#pnherenowoccupantdata) for more details. |

#### PNHereNowOccupantData

| Property Name | Type | Description |
| --- | --- | --- |
| `Uuid` | string | `UUIDs` of the user. |
| `State` | object | `State` of the user. |

### Other examples

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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
pubnub.HereNow()
    // tailor the next two lines to example
    .Channels(new string[] {
        "coolChannel",
        "coolChannel2"
        })
    .IncludeUUIDs(true)
    .Execute(new PNHereNowResultEx(
        (result, status) => {
            if (status.Error) {
                // handle error
                return;
            }

            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("uuid: {0}", occupant.Uuid));
                            Console.WriteLine(string.Format("state:{1}", (occupant.State != null) ?
                            pubnub.JsonPluggableLibrary.SerializeToJsonString(occupant.State) : ""));
                        }
                    }
                }
            }
        }
    ));
```

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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
PNResult<PNHereNowResult> herenowResponse = await pubnub.HereNow()
    .Channels(new string[] {
        // who is present on those channels?
        "my_channel"
    })
    .IncludeState(true) // include state with request (false by default)
    .IncludeUUIDs(true) // if false, only shows occupancy count
    .ExecuteAsync();

PNHereNowResult herenowResult = herenowResponse.Result;
PNStatus status = herenowResponse.Status;
//handle it
```

#### Example response

```csharp
{
    "status" : 200,
    "message" : "OK",
    "service" : "Presence",
    "uuids" : [
        {
            "uuid" : "myUUID0"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 15
                }
            },
            "uuid" : "myUUID1"
        },
        {
            "uuid" : "b9eb408c-bcec-4d34-b4c4-fabec057ad0d"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 15
                }
            },
            "uuid" : "myUUID2"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 24
                }
            },
            "uuid" : "myUUID9"
        }
    ],
    "occupancy" : 5
}
```

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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
PNResult<PNHereNowResult> herenowResponse = await pubnub.HereNow()
    .Channels(new string[] {
            // who is present on those channels?
        "my_channel"
    })
    .IncludeState(false) // include state with request (false by default)
    .IncludeUUIDs(false) // if false, only shows occupancy count
    .ExecuteAsync();

PNHereNowResult herenowResult = herenowResponse.Result;
PNStatus status = herenowResponse.Status;
//handle it
```

#### Example response

```csharp
{
    "status": 200,
    "message": "OK",
    "payload": {
        "channels": {
            "81d8d989-b95f-443c-a726-04fac323b331": {
                "uuids": [ "70fc1140-22b5-4abc-85b2-ff8c17b24d59" ],
                "occupancy": 1
            },
            "81b7a746-d153-49e2-ab70-3037a75cec7e": {
                "uuids": [ "91363e7f-584b-49cc-822c-52c2c01e5928" ],
                "occupancy": 1
            },
            "c068d15e-772a-4bcd-aa27-f920b7a4eaa8": {
                "uuids": [ "ccfac1dd-b3a5-4afd-9fd9-db11aeb65395" ],
                "occupancy": 1
            }
        },
        "total_channels": 3,
        "total_occupancy": 3
    },
    "service": "Presence"
}
```

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

```csharp
pubnub.WhereNow()
        .Uuid(string)
        .QueryParam(Dictionary<string,object>)
```

| Parameter | Description |
| --- | --- |
| `Uuid` *Type: string | `Uuid`. |
| `QueryParam`Type: Dictionary`<string, object>` | Dictionary `object` to pass name/value pairs as query `string` params with PubNub URL request for debug purpose. |
| AsyncType: PNCallback | PNCallback of type PNWhereNowResult. This parameter is deprecated and will be removed in a future version. Please use the `ExecuteAsync` parameter instead. |
| `Execute` *Type: Command | `PNCallback` of type `PNWhereNowResult`. |
| `ExecuteAsync`Type: None | Returns `PNResult<PNWhereNowResult>`. |

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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
PNResult<PNWhereNowResult> wherenowResponse = await pubnub.WhereNow()
    .ExecuteAsync();

PNWhereNowResult wherenowResult = wherenowResponse.Result;
PNStatus status = wherenowResponse.Status;
// returns a pojo with channels
// channel groups which I am part of.
```

### Returns

The `WhereNow()` operation returns a `PNResult<PNWhereNowResult>` which contain the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `Result` | PNWhereNowResult | Returns a `PNWhereNowResult` object. |
| `Status` | PNStatus | Returns a `PNStatus` object. |

`PNWhereNowResult` contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `Channels` | List`<string>` | The list of `channels` where the `UUID` is present. |

### Other examples

#### Get a list of channels synchronously

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
pubnub.WhereNow()
    .Execute(new PNWhereNowResultExt(
        (result, status) => {
            // returns a pojo with channels
            // channel groups which I am part of.
        }
    ));
```

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

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
PNResult<PNWhereNowResult> wherenowResponse = await pubnub.WhereNow()
    .Uuid("some-other-uuid") // uuid of the user we want to spy on.
    .ExecuteAsync();

PNWhereNowResult wherenowResult = wherenowResponse.Result;
PNStatus status = wherenowResponse.Status;
// returns a pojo with channels
// channel groups which "some-other-uuid" part of.ere_now_example_1
```

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

The state API is used to set/get key/value pairs specific to a subscriber `Uuid`.

State information is supplied as a Generic Dictionary object(`Dictionary<string, object>`) of key/value pairs.

### Method(s)

#### Set state

```csharp
pubnub.SetPresenceState()
        .Channels(Array)
        .ChannelGroups(Array)
        .State(Dictionary<string, object>)
        .Uuid(string)
        .QueryParam(Dictionary<string,object>)
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: Array | `Channels` to set `state`. |
| `ChannelGroups`Type: Array | `ChannelGroups` to set `state`. |
| `State`Type: Dictionary`<string, object>` | `State` to set. |
| `Uuid` *Type: string | `Uuid` |
| `QueryParam`Type: Dictionary`<string, object>` | Dictionary `object` to pass name/value pairs as query `string` params with PubNub URL request for debug purpose. |
| AsyncType: PNCallback | PNCallback of type PNSetStateResult. This parameter is deprecated and will be removed in a future version. Please use the `ExecuteAsync` parameter instead. |
| `Execute` *Type: PNCallback | `PNCallback` of type `PNSetStateResult`. |
| `ExecuteAsync`Type: None | Returns `PNResult<PNSetStateResult>`. |

#### Get state

```csharp
pubnub.GetPresenceState()
        .Channels(Array)
        .ChannelGroups(Array)
        .Uuid(string)
        .QueryParam(Dictionary<string,object>)
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: Array | `Channel` name to fetch the `state`. |
| `ChannelGroups`Type: Array | `ChannelGroups` name to fetch the `state`. |
| `Uuid` *Type: string | `Uuid` |
| `QueryParam`Type: Dictionary`<string, object>` | Dictionary `object` to pass name/value pairs as query `string` params with PubNub URL request for debug purpose. |
| AsyncType: PNCallback | PNCallback of type PNGetStateResult. This parameter is deprecated and will be removed in a future version. Please use the `ExecuteAsync` parameter instead. |
| `Execute` *Type: PNCallback | `PNCallback` of type `PNGetStateResult`. |
| `ExecuteAsync`Type: None | Returns PNResult`<PNGetStateResult>`. |

### Sample code

#### Set state

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

#### Get state

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
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
```

### Returns

The `SetPresenceState()` operation returns a `PNResult<PNSetStateResult>` which contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `Result` | PNGetStateResult | Returns a `PNSetStateResult` object. |
| `Status` | PNStatus | Returns a `PNStatus` object. |

`PNSetStateResult` contains the following property:

| Property Name | Type | Description |
| --- | --- | --- |
| `State` | Dictionary`<string, object>` | Dictionary of `UUIDs` and the user states. |

The `GetPresenceState()` operation returns a `PNResult<PNGetStateResult>` which contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `Result` | PNGetStateResult | Returns a `PNGetStateResult` object. |
| `Status` | PNStatus | Returns a `PNStatus` object. |

`PNGetStateResult` contains the following property:

| Property Name | Type | Description |
| --- | --- | --- |
| `StateByUUID` | Dictionary`<string, object>` | Dictionary of `UUIDs` and the user states. |

### Other examples

#### Set state synchronously

```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);

pubnub.SetPresenceState()
    .Channels(new string[] {
        "ch1",
        "ch2",
        "ch3"
    })
    .State(myState)
    .Execute(new PNSetStateResultExt(
        (result, status) => {
            // handle set state response
        }
    ));
```

#### Get state synchronously

```csharp
using PubnubApi;

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

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
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
    .Execute(new PNGetStateResultExt(
        (result, status) => {
            // handle response
        }
    ));
```

#### Set state for channels in channel group

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

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

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