---
source_url: https://www.pubnub.com/docs/pub-sub/subscribe/receive-messages
title: Receive messages
updated_at: 2026-09-30T07:20:08.000Z
---

# Receive messages

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

This guide shows you how to receive messages and other real-time events from a PubNub [channel](https://www.pubnub.com/docs/architecture/core-concepts.md#channel). In an entity-capable SDK, that's three steps: create a subscription, register a handler on it, and call `subscribe()`.

* Create a subscription from a channel, and register a handler that receives its messages.
* Register handlers for the other event types a subscription delivers.
* Subscribe to several channels at once with a subscription set.
* Receive presence events on the same subscription.

Every call on this page needs an SDK instance initialized with your subscribe key. If you don't have a keyset yet, start with [Set up your account](https://www.pubnub.com/docs/architecture/authentication/set-up-your-account.md). If you already have a subscription and only need to add a handler for a different event type, skip to [Register handlers for other event types](#register-handlers-for-other-event-types).

Not every SDK supports entities yet. If yours doesn't, skip to [Use the pattern for SDKs without entities](#use-the-pattern-for-sdks-without-entities).

## Create a subscription and register a handler

Call `.channel()` on your PubNub instance to create a channel entity, then `.subscription()` on that entity to scope a subscription to it. Register a handler on the subscription, then call `subscribe()` to start receiving.

### JavaScript

```javascript
const channel = pubnub.channel('channel_1');
const subscription = channel.subscription();

subscription.onMessage = (messageEvent) => {
  console.log('Message received:', messageEvent.message);
};

subscription.subscribe();
```

### Swift

```swift
let subscription = pubnub.channel("channel_1").subscription()

subscription.onMessage = { message in
  if let text = message.payload[rawValue: "text"] as? String {
    print("Message received: \(text)")
  }
}

subscription.subscribe()
```

### Java

```java
Channel channel = pubnub.channel("channel_1");
Subscription subscription = channel.subscription();

subscription.setOnMessage(event ->
    System.out.println("Message received: " + event.getMessage()));

subscription.subscribe();
```

### Kotlin

```kotlin
val channel = pubnub.channel("channel_1")
val subscription = channel.subscription()

subscription.onMessage = { event ->
    println("Message received: ${event.message}")
}

subscription.subscribe()
```

### C#

```csharp
Subscription subscription = pubnub.Channel("channel_1").Subscription();

subscription.onMessage += (Pubnub pn, PNMessageResult<object> messageEvent) =>
{
    Console.WriteLine($"Message received: {messageEvent.Message}");
};

subscription.Subscribe<object>();
```

### Python

```python
subscription = pubnub.channel('channel_1').subscription()

def on_message(message):
    print('Message received:', message.message)

subscription.on_message = on_message

subscription.subscribe()
```

Registering the handler and calling `subscribe()` are two separate steps, and the order between them doesn't matter as long as both happen. Nothing arrives until `subscribe()` runs, and a handler registered after it fires identically to one registered before. For why the model works this way, refer to [A listener is a callback, not a connection](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md#a-listener-is-a-callback-not-a-connection).

## Register handlers for other event types

A subscription delivers more than messages. Register a handler the same way for any of the other five client-side event types: signals, presence, [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md), [message actions](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md), and files.

### JavaScript

```javascript
subscription.addListener({
  message: (messageEvent) => { console.log('Message:', messageEvent); },
  presence: (presenceEvent) => { console.log('Presence:', presenceEvent); },
  signal: (signalEvent) => { console.log('Signal:', signalEvent); },
  objects: (objectsEvent) => { console.log('App Context:', objectsEvent); },
  messageAction: (messageActionEvent) => { console.log('Message action:', messageActionEvent); },
  file: (fileEvent) => { console.log('File:', fileEvent); },
});
```

### Java

```java
subscription.setOnMessage(event -> { /* Handle message */ });
subscription.setOnSignal(event -> { /* Handle signal */ });
subscription.setOnPresence(event -> { /* Handle presence, requires receivePresenceEvents */ });
subscription.setOnMessageAction(event -> { /* Handle message action */ });
subscription.setOnFile(event -> { /* Handle file event */ });
subscription.setOnUuidMetadata(event -> { /* Handle App Context user metadata event */ });
subscription.setOnChannelMetadata(event -> { /* Handle App Context channel metadata event */ });
subscription.setOnMembership(event -> { /* Handle App Context membership event */ });
```

### Kotlin

```kotlin
subscription.onMessage = { message -> /* Handle message */ }
subscription.onSignal = { signal -> /* Handle signal */ }
subscription.onPresence = { presence -> /* Handle presence, requires receivePresenceEvents */ }
subscription.onMessageAction = { messageAction -> /* Handle message action */ }
subscription.onFile = { file -> /* Handle file event */ }
subscription.onObjects = { obj -> /* Handle App Context event */ }
```

### C#

```csharp
subscription.onMessage += (Pubnub pn, PNMessageResult<object> e) => { /* Handle message */ };
subscription.onPresence += (Pubnub pn, PNPresenceEventResult e) => { /* Handle presence, requires ReceivePresenceEvents */ };
subscription.onSignal += (Pubnub pn, PNSignalResult<object> e) => { /* Handle signal */ };
subscription.onMessageAction += (Pubnub pn, PNMessageActionEventResult e) => { /* Handle message action */ };
subscription.onFile += (Pubnub pn, PNFileEventResult e) => { /* Handle file event */ };
subscription.onObjects += (Pubnub pn, PNObjectEventResult e) => { /* Handle App Context event */ };
```

### Python

```python
subscription.on_message = lambda message: None       # Handle message
subscription.on_signal = lambda signal: None          # Handle signal
subscription.on_presence = lambda presence: None      # Handle presence, requires receivePresenceEvents
subscription.on_message_action = lambda action: None  # Handle message action
subscription.on_file = lambda file: None               # Handle file event
```

Each SDK also offers a generic-listener call that registers several of these handlers in one object instead of one property at a time. Go and Objective-C predate entities and expose only one of the two styles. For that contrast per SDK, and for what a handler receives when it fires, refer to [Two ways to register a handler](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md#two-ways-to-register-a-handler) and [Client-side events](https://www.pubnub.com/docs/architecture/events.md#client-side-events).

## Subscribe to several channels with a subscription set

Build a subscription set from channel names, register handlers on the set instead of on each subscription, and call `subscribe()` once to activate every member.

### JavaScript

```javascript
const subscriptionSet = pubnub.subscriptionSet({ channels: ['chats.room1', 'chats.room2'] });

subscriptionSet.onMessage = (messageEvent) => {
  console.log('Message received:', messageEvent.message);
};

subscriptionSet.subscribe();
```

### Kotlin

```kotlin
val subscriptionSet = pubnub.subscriptionSetOf(channels = setOf("chats.room1", "chats.room2"))

subscriptionSet.onMessage = { event ->
    println("Message received: ${event.message}")
}

subscriptionSet.subscribe()
```

A handler registered on a set fires for every member's events, with no separation between them unless you branch on the channel field yourself. For the other way to build a set, from `Subscription` objects you already created, and for how a set's scope differs from a single subscription's, refer to [Two ways to build a subscription set](https://www.pubnub.com/docs/pub-sub/subscribe/subscriptions.md#two-ways-to-build-a-subscription-set).

## Receive presence events

Pass `receivePresenceEvents: true` when you create the subscription. Without it, a registered `onPresence` handler is never called, no matter how the subscription was built.

```javascript
const subscription = pubnub.channel('channel_1').subscription({ receivePresenceEvents: true });
```

This also requires the Presence add-on enabled on your keyset. For the five presence event subtypes and what each one carries, refer to [Presence](https://www.pubnub.com/docs/architecture/events.md#presence). For the option itself and where it can and can't be set, refer to [Whether a subscription receives presence events](https://www.pubnub.com/docs/pub-sub/subscribe/subscriptions.md#whether-a-subscription-receives-presence-events).

## Use the pattern for SDKs without entities

SDKs that predate entities have no `.channel()` or `.subscription()` call. Register every handler on the PubNub client object with `addListener()`, then subscribe by passing channel names directly to the client's `subscribe()` call. Every handler then fires for every channel that client is subscribed to, with no per-channel separation.

### Objective-C

```objectivec
// The listener's class must conform to the PNEventsListener protocol.
[pubnub addListener:self];

- (void)client:(PubNub *)client didReceiveMessage:(PNMessageResult *)message {
    NSLog(@"Message received: %@", message.data.message);
}

[pubnub subscribeToChannels:@[@"channel_1"] withPresence:NO];
```

### Go

```go
listener := pubnub.NewListener()

go func() {
    for {
        select {
        case message := <-listener.Message:
            fmt.Println("Message received:", message.Message)
        }
    }
}()

pn.AddListener(listener)

pn.Subscribe().
    Channels([]string{"channel_1"}).
    Execute()
```

Check your platform's [API reference](https://www.pubnub.com/docs/sdks.md) before assuming either model applies to your SDK version. For why the split exists and what it costs you, refer to [Listener scope follows the subscription, not the channel name](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md#listener-scope-follows-the-subscription-not-the-channel-name).

## Related tasks

* [Event listeners](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md). The listener model, the two registration styles per SDK, and how handler scope works.
* [Subscriptions and subscription sets](https://www.pubnub.com/docs/pub-sub/subscribe/subscriptions.md). The object model behind a subscription, and how `subscribe()` and `unsubscribe()` change its state.
* [Events](https://www.pubnub.com/docs/architecture/events.md). Every event type, what triggers it, and the fields its payload carries.
* [Filter received messages](https://www.pubnub.com/docs/pub-sub/subscribe/filter-received-messages.md). Narrow what reaches a client before it arrives.
* [Stop receiving messages](https://www.pubnub.com/docs/pub-sub/subscribe/stop-receiving-messages.md). Remove a handler and unsubscribe.
* [Subscribe](https://www.pubnub.com/docs/pub-sub/subscribe/overview.md). Multiplexing, channel groups, wildcards, and what a client is eligible to receive.

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