---
source_url: https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe
title: Publish/Subscribe API for JavaScript SDK
updated_at: 2026-06-04T11:11:58.477Z
sdk_name: PubNub JavaScript SDK
sdk_version: 11.0.1
---

> 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


# Publish/Subscribe API for JavaScript SDK

PubNub JavaScript SDK, use the latest version: 11.0.1

Install:

```bash
npm install pubnub@11.0.1
```

PubNub delivers messages worldwide in less than 30 ms. Send a message to one recipient or broadcast to thousands of subscribers.

For higher-level conceptual details on publishing and subscribing, refer to [Connection Management](https://www.pubnub.com/docs/general/setup/connection-management) and to [Publish Messages](https://www.pubnub.com/docs/general/messages/publish).

:::note Supported and recommended asynchronous patterns
PubNub supports [Callbacks, Promises, and Async/Await](https://javascript.info/async) for asynchronous JS operations. The recommended pattern is Async/Await and all sample requests in this document are based on it. This pattern returns a status only on detecting an error. To receive the status errors, you must use the [try...catch](https://javascript.info/try-catch) syntax in your code.
:::

## Publish

`publish()` sends a message to all channel subscribers. PubNub replicates the message across its points of presence and delivers it to all subscribed clients on that channel.

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#initialization) with the `publishKey`.
* You don't have to be subscribed to a channel to publish to it.
* You cannot publish to multiple channels simultaneously.

### Security

Secure messages with Transport Layer Security (TLS) or Secure Sockets Layer (SSL) by setting `ssl` to `true` during [initialization](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration). You can also [encrypt](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#cryptomodule) messages.

### Message data

The message can contain any JavaScript Object Notation (JSON)-serializable data (objects, arrays, integers, strings). Avoid special classes or functions. Strings can include any UTF‑8 characters.

:::warning Don't JSON serialize
You should not JSON serialize the `message` and `meta` parameters when sending signals, messages, or files as the serialization is automatic. Pass the full object as the message/meta payload and let PubNub handle everything.
:::

### Size

The maximum message size is 32 KiB. This includes the escaped character count and the channel name. Aim for under 1,800 bytes for optimal performance.

If your message exceeds the limit, you'll receive a `Message Too Large` error. To learn more or calculate payload size, see [Message size limits](https://www.pubnub.com/docs/general/messages/publish#message-size-limit).

:::tip Need larger messages?
Our platform is optimized for payloads up to 32 KiB. PubNub supports larger messages, but increasing the limit requires a verification of compatibility with your use case.
Talk to [our team](https://www.pubnub.com/company/contact-sales/) to discuss increasing the message size limit for your use case.
:::

### Publish rate

You can publish as fast as bandwidth allows. There is a [soft throughput limit](https://www.pubnub.com/docs/general/setup/limits) because messages may drop if subscribers can't keep up.

For example, publishing 200 messages at once may cause the first 100 to drop if a subscriber hasn't received any yet. The in-memory queue stores only 100 messages.

### Custom message type

You can optionally provide the `customMessageType` parameter to add your business-specific label or category to the message, for example `text`, `action`, or `poll`.

### Best practices

* Publish to a channel serially (not concurrently).
* Verify a success return code (for example, `[1,"Sent","136074940..."]`).
* Publish the next message only after a success return code.
* On failure (`[0,"blah","<timetoken>"]`), retry.
* Keep the in-memory queue under 100 messages to avoid drops.
* Throttle bursts to meet latency needs (for example, no more than 5 messages per second).

### Method(s)

To `Publish a message`, you can use the following method(s) in the JavaScript SDK:

```javascript
pubnub.publish({
    message: any,
    channel: string,
    meta: any,
    storeInHistory: boolean,
    sendByPost: boolean,
    ttl: number,
    customMessageType: string
}): Promise<PublishResponse>;
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| message | any | Yes |  | The `message` may be any valid JSON type including objects, arrays, strings, and numbers. |
| channel | string | Yes |  | Specifies the `channel` ID to publish messages to. |
| storeInHistory | boolean | Optional | `true` | If `true` the messages are stored in history. If `storeInHistory` is not specified, then the history configuration on the key is used. |
| sendByPost | boolean | Optional | `false` | When `true`, the SDK uses HTTP POST to publish the messages. The message is sent in the BODY of the request, instead of the query string when HTTP GET is used. Also the messages are compressed thus reducing the size of the messages. Using HTTP POST to publish messages adheres to RESTful API best practices. |
| meta | any | Optional |  | Publish extra `meta` with the request. |
| ttl | number | Optional |  | Set a per message time to live in Message Persistence. If storeInHistory = true, and ttl = 0, the message is stored with no expiry time., If storeInHistory = true and ttl = X (X is an Integer value), the message is stored with an expiry time of X hours unless you have message retention set to Unlimited on your keyset configuration in the Admin Portal., If storeInHistory = false, the ttl parameter is ignored., If ttl is not specified, then expiration of the message defaults back to the expiry value for the key. |
| customMessageType | string | Optional |  | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

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

#### Publish a message to a channel

```javascript
import PubNub from 'pubnub';
// Initialize PubNub with your keys
const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});
```

```javascript
try {
  const response = await pubnub.publish({
    message: { text: 'Hello World' },
    channel: 'my_channel',
    sendByPost: false,
    storeInHistory: true,
    meta: { sender: 'user123' },
    customMessageType: 'text-message',
  });
  console.log('Publish Success:', response);
} catch (error) {
  console.error(
    `Publish Failed: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

:::note Subscribe to the channel
Before running the above publish example, either using the [Debug Console](https://www.pubnub.com/docs/console/) or in a separate script running in a separate terminal window, [subscribe to the same channel](#subscribe) that is being published to.
:::

### Response

```json
type PublishResponse = {
    timetoken: number
}
```

### Other examples

#### Publish a JSON-serialized message

```javascript
const newMessage = {
  text: 'Hi There!',
};

try {
  const response = await pubnub.publish({
    message: newMessage,
    channel: 'my_channel',
    customMessageType: 'text-message',
  });

  console.log('message published with server response:', response);
} catch (error) {
  console.error(
    `Publish Failed: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

#### Store the published message for 10 hours

```javascript
try {
  const response = await pubnub.publish({
    message: 'hello!',
    channel: 'my_channel',
    storeInHistory: true,
    ttl: 10,
    customMessageType: 'text-message',
  });

  console.log('message published with server response:', response);
} catch (error) {
  console.error(
    `Publish Failed: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

#### Publish successful

```javascript
const response = await pubnub.publish({
  message: 'hello world!',
  channel: 'ch1',
});

console.log(response); // {timetoken: "14920301569575101"}
// end.snippet
```

#### Publish unsuccessful by network down

```javascript
try {
  const response = await pubnub.publish({
    message: 'hello world!',
    channel: 'ch1',
  });
  console.log('message published with server response:', response);
} catch (error) {
  console.error(
    `Publish Failed: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

#### Publish unsuccessful by initialization without a publish key

```javascript
try {
  const result = await pubnub.publish({
    message: 'hello world!',
    channel: 'ch1',
  });
  console.log('message published with server response:', response);
} catch (error) {
  console.error(
    `Publish Failed: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

## Fire

The fire endpoint sends a message to Functions event handlers and [Illuminate](https://www.pubnub.com/docs/illuminate/business-objects/external-data-sources). The message goes directly to handlers registered on the target channel and triggers their execution. The handler can read the request body. Messages sent via `fire()` aren't replicated to subscribers and aren't stored in history.

### Method(s)

To `Fire a message`, you can use the following method(s) in the JavaScript SDK:

```javascript
fire({
    Object message,
    String channel,
    Boolean sendByPost,
    Object meta
})
```

| Parameter | Description |
| --- | --- |
| `message` *Type: ObjectDefault: n/a | The `message` may be any valid JSON type including objects, arrays, strings, and numbers. |
| `channel` *Type: StringDefault: n/a | Specifies `channel` ID to publish messages to. |
| `sendByPost`Type: BooleanDefault: `false` | If `true` the messages sent via POST. |
| `meta`Type: ObjectDefault: n/a | Publish extra `meta` with the request. |

### Sample code

#### Fire a message to a channel

```javascript
// Initialize PubNub with your keys
try {
  const response = await pubnub.fire({
    message: {
      such: 'object',
    },
    channel: 'my_channel',
    sendByPost: false, // true to send via post
    meta: {
      cool: 'meta',
    }, // fire extra meta with the request
  });

  console.log(`message published with timetoken: ${response.timetoken}`);
} catch (error) {
  // handle error
  console.error(
    `Fire failed with error: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

## Signal

The `signal()` function sends a signal to all subscribers of a channel.

By default, signals are limited to a message payload size of `64` bytes. This limit applies only to the payload, and not to the URI or headers. If you require a larger payload size, please [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Method(s)

To `Signal a message`, you can use the following method(s) in the JavaScript SDK:

```javascript
pubnub.signal({
    message: string,
    channel: string,
    customMessageType: string,
}): Promise<SignalResponse>;
```

| Parameter | Description |
| --- | --- |
| `message` *Type: string | The `message` may be any valid JSON type including objects, arrays, strings, and numbers. |
| `channel` *Type: string | Specifies `channel` ID to send messages to. |
| `customMessageType`Type: string | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

### Sample code

#### Signal a message to a channel

```javascript
try {
  const response = await pubnub.signal({
    message: 'hello',
    channel: 'foo',
    customMessageType: 'text-message',
  });
  console.log('signal response:', response);
} catch (error) {
  // handle error
  console.error(
    `Signal failed with error: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

### Response

```javascript
type SignalResponse = {
    timetoken: number
}
```

## Subscribe

The subscribe function creates an open TCP socket to PubNub and begins listening for messages and events on a specified entity or set of entities. To subscribe successfully, configure the appropriate `subscribeKey` at [initialization](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#initialization).

:::tip Conceptual overview
For more general information about subscriptions, refer to [Subscriptions](https://www.pubnub.com/docs/general/channels/subscribe).
:::

Entities are [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) that provide access to their encapsulated APIs. You can subscribe using the PubNub client object or directly on a specific entity:

* [channel](#create-channels)
* [channelGroup](#create-channel-groups)
* [userMetadata](#create-user-metadata)
* [channelMetadata](#create-channel-metadata)

A newly subscribed client receives messages after the `subscribe()` call completes. You can configure [retryConfiguration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#initialization) to automatically attempt to reconnect and retrieve any available messages if a client gets disconnected.

:::warning Subscribe only opens the connection
Calling `subscribe()` opens a connection but doesn't deliver messages to your code. You must also add [event listeners](#event-listeners) to receive messages and access sender information. The message object received through listeners includes the sender's ID in the `publisher` field.
:::

### Subscription scope

Subscriptions let you attach listeners for specific real-time update types. Your app receives messages and events through those listeners. There are two types:

* [subscription](#create-a-subscription): created from an entity and scoped to that entity (for example, a particular channel)
* [subscriptionSet](#create-a-subscription-set): created from the PubNub client and scoped to the client (for example, all subscriptions created on a single `pubnub` object). A set can include one or more subscriptions.

The event listener is a single point through which your app receives all the messages, signals, and events in the entities you subscribed to. For information on adding event listeners, refer to [Event listeners](#event-listeners).

:::tip Add subscriptions to an existing set
If you subscribe to a subscription set and then [add more subscriptions](#add-subscriptions-to-an-existing-set) to it, they are automatically subscribed to.
:::

### Create a subscription

An entity-level `subscription` allows you to receive messages and events for only that entity for which it was created. Using multiple entity-level `subscription`s is useful for handling various message/event types differently in each channel.

```javascript
// entity-based, local-scoped
const channel = pubnub.channel('channel_1');
channel.subscription(subscriptionOptions)
```

| Parameter | Description |
| --- | --- |
| `subscriptionOptions`Type: `subscriptionOptions` | `Subscription` [behavior configuration](#subscriptionoptions). |

### Create a subscription set

A client-level `subscriptionSet` allows you to receive messages and events for all entities in the set. A single `subscriptionSet` is useful for similarly handling various message/event types in each channel.

```javascript
// client-based, general-scoped
pubnub.subscriptionSet({
    channels: string[],
    channelGroups: string[],
    subscriptionOptions: subscriptionOptions
}))
```

| Parameter | Description |
| --- | --- |
| `> channels`Type: `string[]` | Channels to subscribe to. Either `channels` or `channelGroups` is mandatory. |
| `> channelGroups`Type: `string[]` | Channel groups to subscribe to. Either `channels` or `channelGroups` is mandatory. |
| `> subscriptionOptions`Type: `subscriptionOptions` | `Subscription` [behavior configuration](#subscriptionoptions). |

#### subscriptionOptions

`subscriptionOptions` is a class. Available properties include:

| Option | Type | Description |
| --- | --- | --- |
| `receivePresenceEvents` | boolean | Whether presence updates for `userId`s should be delivered through the listener streams. 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). |
| `cursor` | object | Cursor from which to return any available cached messages. Message retrieval with cursor is not guaranteed and should only be considered a best-effort service. A cursor consists of a timetoken and region: `cursor?: { timetoken?: string; region?: number }` If you pass any primitive type, the SDK converts them into `SubscriptionCursor` but if their value is not a 17-digit number or a string with numeric characters, the provided value will be ignored. |

#### Modify a subscription set

You can add and remove subscriptions to and from an existing set to create new sets. If you subscribe to a subscription set and then [add more subscriptions](#add-subscriptions-to-an-existing-set) to it, they are automatically subscribed to.

Refer to the [Other examples](#other-examples-1) section for more information on adding and removing subscriptions.

### Method(s)

`subscription` and `subscriptionSet` use the same `subscribe()` method.

#### Subscribe

To subscribe, you can use the following method in the JavaScript SDK:

```javascript
subscription.subscribe()
subscriptionSet.subscribe()
```

##### Sample code

###### JavaScript

```javascript
const channelsSubscriptionSet = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });
channelsSubscriptionSet.subscribe();
```

###### React

In React, create the subscription inside a `useEffect` hook and unsubscribe in the cleanup function to avoid memory leaks when the component unmounts.

```jsx
import React, { useEffect } from 'react';
import PubNub from 'pubnub';

const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});

function SubscribedComponent() {
  useEffect(() => {
    const channel = pubnub.channel('my_channel');
    const subscription = channel.subscription({
      receivePresenceEvents: true,
    });
    subscription.subscribe();

    return () => {
      subscription.unsubscribe();
    };
  }, []);

  return <div>Subscribed to my_channel</div>;
}
```

:::note Wildcard subscribe and message objects
Wildcard subscribe (e.g., `sports.*`) works the same as regular subscribe - you still need to add event listeners to receive messages. The message objects received include the sender's ID in the `publisher` field, the actual channel name in the `channel` field, and the wildcard match in the `subscription` field.
:::

##### Other examples

###### Create a subscription set from 2 individual subscriptions

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription1 = channel.subscription({ receivePresenceEvents: true });

// create a subscription from a channel group entity
const channelGroup = pubnub.channelGroup('channelGroup_1');
const subscription2 = channelGroup.subscription();

// add 2 subscriptions to create a subscription set
const subscriptionSet = subscription1.addSubscription(subscription2);

// add another subscription to the set
const subscription3 = pubnub.channel('channel_3').subscription({ receivePresenceEvents: false });
subscriptionSet.addSubscription(subscription3);

// remove a subscription from a subscription set
subscriptionSet.removeSubscription(subscription3);

subscriptionSet.subscribe();
```

###### Create a subscription set from 2 sets

```javascript
// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// create another subscription set with multiple channels and options
const subscriptionSet2 = pubnub.subscriptionSet({
  channels: ['ch3', 'ch4'],
  subscriptionOptions: { receivePresenceEvents: true },
});

// add a subscription set to another subscription set
subscriptionSet1.addSubscriptionSet(subscriptionSet2);

// remove a subscription set from another subscription set
subscriptionSet1.removeSubscriptionSet(subscriptionSet2);
```

###### Add subscriptions to an existing set

```javascript
// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// subscribe to the set
// start receiving events from ch1 and ch2
subscriptionSet1.subscribe();

// create another subscription set with multiple channels
const subscriptionSet2 = pubnub.subscriptionSet({ channels: ['ch3', 'ch4'] });

// add the new set to the initial set
subscriptionSet1.addSubscriptionSet(subscriptionSet2);

// you're now receiving events from ch1, ch2, ch3, and ch4
// because the set has been subscribed to previously

// create and add another subscription to the set
const channelGroup = pubnub.channelGroup('channelGroup_1');
const subscription2 = channelGroup.subscription();
subscriptionSet1.addSubscription(subscription2);

// you're now receiving events from ch1, ch2, ch3, and ch4 and channelGroup_1
```

##### Returns

The `subscribe()` method doesn't have a return value.

## Entities

Entities are subscribable objects for which you can receive real-time updates (messages, events, etc).

* [channel](#create-channels)
* [channelGroup](#create-channel-groups)
* [userMetadata](#create-user-metadata)
* [channelMetadata](#create-channel-metadata)

### Create channels

This method returns a local `channel` entity.

```javascript
pubnub.channel(string)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: `string` | The ID of the [channel](https://www.pubnub.com/docs/general/channels/overview) to create a subscription of. |

#### Sample code

```javascript
const channel = pubnub.channel('my_channel');
```

### Create channel groups

This method returns a local `channelGroup` entity.

```javascript
pubnub.channelGroup(string)
```

| Parameter | Description |
| --- | --- |
| `channel_group` *Type: `string` | The name of the [channel group](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to create a subscription of. |

#### Sample code

```javascript
// Initialize PubNub with demo keys
const channelGroup = pubnub.channelGroup('channelGroup_1');
```

### Create channel metadata

This method returns a local `channelMetadata` entity.

```javascript
pubnub.channelMetadata(string)
```

| Parameter | Description |
| --- | --- |
| `channelMetadata` *Type: `string` | The String identifier of the [channel metadata](https://www.pubnub.com/docs/general/metadata/channel-metadata) object to create a subscription of. |

#### Sample code

```javascript
// Initialize PubNub with demo keys

const channelMetadata = pubnub.channelMetadata('channel_1');
```

### Create user metadata

This method returns a local `userMetadata` entity.

```javascript
pubnub.userMetadata(string)
```

| Parameter | Description |
| --- | --- |
| `userMetadata` *Type: `string` | The String identifier of the [user metadata](https://www.pubnub.com/docs/general/metadata/users-metadata) object to create a subscription of. |

#### Sample code

```javascript
// Initialize PubNub with demo keys

const userMetadata = pubnub.userMetadata('user_meta1');
```

## Event listeners

Messages and events are received in your app using a listener. This listener allows a single point to receive all messages, signals, and events.

You can attach listeners to the instances of [subscription](#create-a-subscription), [subscriptionSet](#create-a-subscription-set), and, in the case of the connection status, the PubNub client.

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/general/channels/subscribe-filters) to filter messages server-side before they reach your listener.
:::

### Add listeners

You can implement multiple listeners with the `addListener()` method or register an event-specific listener that receives only a selected type, like `message` or `file`.

#### Method(s)

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription = channel.subscription();

// Event-specific listeners
subscription.onMessage = (message) => {
  console.log('Message event: ', message);
};
subscription.onPresence = (presence) => {
  console.log('Presence event: ', presence);
};
subscription.onSignal = (signal) => {
  console.log('Signal event: ', signal);
};
subscription.onObjects = (objectsEvent) => {
  console.log('Objects event: ', objectsEvent);
};
subscription.onMessageAction = (messageActionEvent) => {
  console.log('Message Reaction event: ', messageActionEvent);
};
subscription.onFile = (fileEvent) => {
  console.log('File event: ', fileEvent);
};

// Generic listeners
subscription.addListener({
  // Messages
  message: function (m) {
    const channelName = m.channel; // Channel on which the message was published
    const channelGroup = m.subscription; // Channel group or wildcard subscription match (if exists)
    const pubTT = m.timetoken; // Publish timetoken
    const msg = m.message; // Message payload
    const publisher = m.publisher; // Message publisher
  },
  // Presence
  // requires a subscription with presence
  presence: function (p) {
    const action = p.action; // Can be join, leave, timeout, state-change, or interval
    const channelName = p.channel; // Channel to which the message belongs
    const channelGroup = p.subscription; //  Channel group or wildcard subscription match, if any
    const publishTime = p.timestamp; // Publish timetoken
    const timetoken = p.timetoken; // Current timetoken
  },
  // Signals
  signal: function (s) {
    const channelName = s.channel; // Channel to which the signal belongs
    const channelGroup = s.subscription; // Channel group or wildcard subscription match, if any
    const pubTT = s.timetoken; // Publish timetoken
    const msg = s.message; // Payload
    const publisher = s.publisher; // Message publisher
  },
  // App Context
  objects: (objectEvent) => {
    const channel = objectEvent.channel; // channel Id or a User Id of updated/set app context metadata object
    const channelGroup = objectEvent.subscription; // Channel group
    const timetoken = objectEvent.timetoken; // Event timetoken
    const event = objectEvent.message.data.type; // Event name
  },
  // Message Actions
  messageAction: function (ma) {
    const channelName = ma.channel; // Channel to which the message belongs
    const publisher = ma.data.uuid; // Message publisher
    const event = ma.event; // Message action added or removed
    const type = ma.data.type; // Message action type
    const value = ma.data.value; // Message action value
    const messageTimetoken = ma.data.messageTimetoken; // Timetoken of the original message
    const actionTimetoken = ma.data.actionTimetoken; // Timetoken of the message action
  },
  // File Sharing
  file: function (event) {
    const channelName = event.channel; // Channel to which the file belongs
    const channelGroup = event.subscription; // Channel group or wildcard subscription match (if exists)
    const publisher = event.publisher; // File publisher
    const timetoken = event.timetoken; // Event timetoken
    const message = event.message; // Optional message attached to the file
  },
});
```

#### Sample code

##### JavaScript

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription1 = channel.subscription({ receivePresenceEvents: true });

// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// add a status listener
pubnub.addListener({
  status: (s) => {
    console.log('Status', s.category);
  },
});

// add message and presence listeners
subscription1.addListener({
  // Messages
  message: (m) => {
    console.log('Received message', m);
  },
  // Presence
  presence: (p) => {
    console.log('Presence event', p);
  },
});

// add event-specific message actions listener
subscriptionSet1.onMessageAction = (p) => {
  console.log('Message action event:', p);
};

subscription1.subscribe();
subscriptionSet1.subscribe();
```

##### React

In React, add listeners inside `useEffect` and remove them in the cleanup function. Update component state from within the listener callbacks to trigger re-renders.

```jsx
import React, { useState, useEffect } from 'react';
import PubNub from 'pubnub';

const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});

function Chat() {
  const [messages, setMessages] = useState([]);
  const [onlineCount, setOnlineCount] = useState(0);
  const [isConnected, setIsConnected] = useState(false);

  useEffect(() => {
    pubnub.addListener({
      message: (event) => {
        setMessages((prev) => [...prev, event.message]);
      },
      presence: (event) => {
        // event.action: 'join' | 'leave' | 'timeout' | 'interval' | 'state-change'
        // occupancy is present on join/leave/timeout/interval but not on state-change
        if (event.action !== 'state-change') setOnlineCount(event.occupancy);
      },
      status: (event) => {
        setIsConnected(event.category === 'PNConnectedCategory');
      },
    });

    const channel = pubnub.channel('my_channel');
    const subscription = channel.subscription({ receivePresenceEvents: true });
    subscription.subscribe();

    return () => {
      subscription.unsubscribe();
      pubnub.removeAllListeners();
    };
  }, []);

  return (
    <div>
      <p>{isConnected ? `Connected — ${onlineCount} online` : 'Connecting...'}</p>
      <ul>
        {messages.map((msg, i) => (
          <li key={i}>{typeof msg === 'object' ? JSON.stringify(msg) : msg}</li>
        ))}
      </ul>
    </div>
  );
}
```

:::note Message object contains sender information
When you receive messages through listeners, the message object includes the sender's ID in the `publisher` field, along with the message content, channel name, timetoken, and other metadata.
:::

### Add connection status listener

The PubNub client has a listener dedicated to handling connection status updates.

:::warning Client scope
This listener is only available on the PubNub object.
:::

#### Method(s)

```javascript
pubnub.addListener({
  status: (s) => s.category,
});
```

#### Sample code

```javascript
// add a status listener
pubnub.addListener({
  status: (s) => {
    console.log('Status', s.category);
  },
});
```

#### Returns

The subscription status. For information about available statuses, refer to [SDK statuses](https://www.pubnub.com/docs/general/setup/connection-management#sdk-statuses).

## Unsubscribe

Stop receiving real-time updates from a [subscription](#create-a-subscription) or a [subscriptionSet](#create-a-subscription-set).

### Method(s)

```javascript
subscription.unsubscribe()

subscriptionSet.unsubscribe()
```

### Sample code

```javascript
// create a subscription from a channel entity
const channel1 = pubnub.channel('channel_1');
const subscription1 = channel1.subscription({ receivePresenceEvents: true });

// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

subscription1.subscribe();
subscriptionSet1.subscribe();

subscription1.unsubscribe();
subscriptionSet1.unsubscribe();
```

### Returns

None

## Unsubscribe all

Stop receiving real-time updates from all data streams and remove the entities associated with them.

:::warning Client scope
This method is only available on the PubNub object.
:::

### Method(s)

```javascript
pubnub.unsubscribeAll()
```

### Sample code

```javascript
// create a subscription set with multiple channels
const subscriptionSet = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });
subscriptionSet.subscribe();

// create a subscription from a channel entity
const channelGroup1 = pubnub.channelGroup('channelGroup_1');
const groupSubscription1 = channelGroup1.subscription({ receivePresenceEvents: true });
groupSubscription1.subscribe();

// unsubscribe all active subscriptions
pubnub.unsubscribeAll();
```

### Returns

None

## Subscribe (old)

:::warning Not recommended
The use of this method is discouraged. Use [Subscribe](#subscribe) instead.
:::

#### Receive messages

Your app receives messages and events via event listeners. The event listener is a single point through which your app receives all the messages, signals, and events that are sent in any channel you are subscribed to.

For more information about adding a listener, refer to the [Event Listeners](#add-listeners-1) section.

#### Description

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified `channel`. To subscribe to a `channel` ID the client must send the appropriate `subscribeKey` at initialization.

By default a newly subscribed client will only receive messages published to the channel after the `subscribe()` call completes.

:::tip Connectivity notification
You can be notified of connectivity via the listener, on establishing connection the `statusEvent.category` returns `PNConnectedCategory`.
By waiting for the connect event to return before attempting to publish, you can avoid a potential race condition on clients that subscribe and immediately publish messages before the `subscribe` has completed.
:::

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

To `Subscribe to a channel`, you can use the following method(s) in the JavaScript SDK:

```javascript
pubnub.subscribe({
    channels: Array<string>,
    channelGroups: Array<string>,
    withPresence: boolean,
    timetoken: number
}): Promise<SubscribeResponse>;
```

| Parameter | Description |
| --- | --- |
| `channels` *Type: Array`<string>`Default: n/a | Specifies the `channels` to subscribe to. It is possible to specify multiple `channels` as a list or as an array. |
| `channelGroups`Type: Array`<string>`Default: n/a | Specifies the `channelGroups` to subscribe to. |
| `withPresence`Type: booleanDefault: `false` | If `true` it also subscribes to presence instances. |
| `timetoken`Type: numberDefault: n/a | Specifies `timetoken` from which to start returning any available cached messages. Message retrieval with timetoken is not guaranteed and should only be considered a best-effort service. |

#### Sample code

Subscribe to a channel:

```javascript
pubnub.subscribe({
  channels: ['my_channel'],
});
```

:::note Event listeners
The response of the call is handled by adding a Listener. Please see the [Event Listeners](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#event-listeners) section for more details. Listeners should be added before calling the method.
:::

#### Returns

##### The following objects will be returned in the status response

| Object | Description |
| --- | --- |
| `category` | `PNConnectedCategory` |
| `operation` | `PNSubscribeOperation` |
| `affectedChannels` | The channels affected in the operation, of type array. |
| `subscribedChannels` | All the current subscribed channels, of type array. |
| `affectedChannelGroups` | The channel groups affected in the operation, of type array. |
| `lastTimetoken` | The last timetoken used in the subscribe request, of type long. |
| `currentTimetoken` | The current timetoken fetched in the subscribe response, which is going to be used in the next request, of type long. |

```json
{
    category: 'PNConnectedCategory',
    operation: 'PNSubscribeOperation',
    affectedChannels: ['my_channel_1'],
    subscribedChannels: ['my_channel_1'],
    affectedChannelGroups: [],
    lastTimetoken: '14974492380756600',
    currentTimetoken: '14974492384874375'
}
```

##### The following objects will be returned in the subscribe message response

| Object | Description |
| --- | --- |
| `channel` | The `channel` ID for which the message belongs. |
| `subscription` | The `channel group` or wildcard subscription match (if exists). |
| `timetoken` | Publish `timetoken`. |
| `message` | The `payload`. |
| actualChannel | Deprecated. Use property `channel`. |
| subscribedChannel | Deprecated. Use property `subscription`. |

```json
{
    actualChannel: null,
    channel: "my_channel_1",
    message: "Hello World!",
    publisher: "pn-58e1a647-3e8a-4c7f-bfa4-e007ea4b2073",
    subscribedChannel: "my_channel_1",
    subscription: null,
    timetoken: "14966804541029440"
}
```

##### The following objects will be returned in the Presence response

| Object | Description |
| --- | --- |
| `action` | Can be `join`, `leave`, `state-change` or `timeout`. |
| `channel` | The `channel` ID for which the message belongs. |
| `occupancy` | No. of users connected with the `channel` ID. |
| `state` | User State. |
| `subscription` | The `channel group` or wildcard subscription match (if exists) |
| `timestamp` | Current `timetoken`. |
| `timetoken` | Publish `timetoken`. |
| `uuid` | UUIDs of users who are connected with the `channel` ID. |

```json
{
    category: 'PNConnectedCategory',
    operation: 'PNSubscribeOperation',
    affectedChannels: ['my_channel_1'],
    subscribedChannels: ['my_channel_1'],
    affectedChannelGroups: [],
    lastTimetoken: '14974492380756600',
    currentTimetoken: '14974492384874375'
}
```

#### Other examples

##### Subscribing to multiple channels

It's possible to subscribe to more than one channel using the [Multiplexing](https://www.pubnub.com/docs/general/channels/subscribe#channel-multiplexing) feature. The example shows how to do that using an array to specify the channel names.

:::note Alternative subscription methods
You can also use [Wildcard Subscribe](https://www.pubnub.com/docs/general/channels/subscribe#wildcard-subscribe) and [Channel Groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to subscribe to multiple channels at a time. To use these features, the *Stream Controller* add-on must be enabled on your keyset in the [Admin Portal](https://admin.pubnub.com).
:::

```javascript
pubnub.subscribe({
  channels: ['my_channel_1', 'my_channel_2', 'my_channel_3'],
});
```

##### Subscribing to a Presence channel

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

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending `-pnpres` to the channel name. For example the channel named `my_channel` would have the presence channel named `my_channel-pnpres`.

```javascript
pubnub.subscribe({
  channels: ['my_channel'],
  withPresence: true,
});
```

##### Wildcard subscribe to channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/) (with Enable Wildcard Subscribe checked). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

Wildcard subscribes allow the client to subscribe to multiple channels using wildcard. For example, if you subscribe to `a.*` you will get all messages for `a.b`, `a.c`, `a.x`. The wildcarded `*` portion refers to any portion of the channel string name after the `dot (.)`.

```javascript
pubnub.subscribe({
  channels: ['ab.*'],
});
```

:::note Wildcard grants and revokes
Only one level (`a.*`) of wildcarding is supported. If you grant on `*` or `a.b.*`, the grant will treat `*` or `a.b.*` as a single channel named either `*` or `a.b.*`. You can also revoke permissions from multiple channels using wildcards but only if you previously granted permissions using the same wildcards. Wildcard revokes, similarly to grants, only work one level deep, like `a.*`.
:::

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

:::note Required UUID
Always set the `UUID` to uniquely identify the user or device that connects to PubNub. This `UUID` should be persisted, and should remain unchanged for the lifetime of the user or the device. If you don't set the `UUID`, you won't be able to connect to PubNub.
:::

```javascript
pubnub.addListener({
  status: async (statusEvent) => {
    if (statusEvent.category === 'PNConnectedCategory') {
      try {
        await pubnub.setState({
          state: {
            some: 'state',
          },
        });
      } catch (error) {
        // handle setState error
      }
    }
  },
  message: (messageEvent) => {
    // handle message
  },
  presence: (presenceEvent) => {
    // handle presence
  },
});

pubnub.subscribe({
  channels: ['ch1', 'ch2', 'ch3'],
});
```

##### Subscribe to a channel group

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.subscribe({
  channelGroups: ['my_channelGroup'],
});
```

##### Subscribe to the presence channel of a channel group

:::note Requires Stream Controller and Presence add-ons
This method requires that both the *Stream Controller* and *Presence* add-ons are enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.subscribe({
  channelGroups: ['family'],
  withPresence: true,
});
```

##### Subscribing to multiple channel groups

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.subscribe({
  channelGroups: ['my_channelGroup1', 'my_channelGroup2', 'my_channelGroup3'],
});
```

##### Subscribing to a channel and channel group simultaneously

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.subscribe({
  channels: ['my_channel'],
  channelGroups: ['my_channelGroup'],
});
```

##### Sample Responses

##### Join event

```json
{
    "channel": "my_channel",
    "subscription": null,
    "actualChannel": null,
    "subscribedChannel": "my_channel-pnpres",
    "action": "join",
    "timetoken": "15119466699655811",
    "occupancy": 2,
    "uuid": "User1",
    "timestamp": 1511946669
}
```

##### Leave event

```json
{
    "channel": "my_channel",
    "subscription": null,
    "actualChannel": null,
    "subscribedChannel": "my_channel-pnpres",
    "action": "leave",
    "timetoken": "15119446002445794",
    "occupancy": 1,
    "uuid": "User1",
    "timestamp": 1511944600
}
```

##### Timeout event

```json
{
    "channel": "my_channel",
    "subscription": null,
    "actualChannel": null,
    "subscribedChannel": "my_channel-pnpres",
    "action": "timeout",
    "timetoken": "15119519897494311",
    "occupancy": 3,
    "uuid": "User2",
    "timestamp": 1511951989
}
```

##### State change event

```json
{
    "channel": "my_channel",
    "subscription": null,
    "actualChannel": null,
    "subscribedChannel": "my_channel-pnpres",
    "action": "state-change",
    "state": {
        "isTyping": true
    },
    "timetoken": "15119477895378127",
    "occupancy": 5,
    "uuid": "User4",
    "timestamp": 1511947789
}
```

##### Interval event

```json
{
    "action": "interval",
    "occupancy": 2,
    "timestamp": 1511947739
}
```

When a channel is in interval mode with `presence_deltas` `pnconfig` flag enabled, the interval message may also include the following fields which contain an array of changed UUIDs since the last interval message.

* joined
* left
* timedout

For example, this interval message indicates there were 2 new UUIDs that joined and 1 timed out UUID since the last interval:

```json
{
    "action":"interval",
    "timestamp":1548340678,
    "occupancy":2,
    "join":["pn-94bea6d1-2a9e-48d8-9758-f1b7162631ed","pn-cecbfbe3-312f-4928-93a2-5a79c91b10e0"]},
    "timedout":["pn-cecbfbe3-312f-4928-93a2-5a79c91b10e0"],
    "b":"my-channel-pnpres"
}
```

If the full interval message is greater than `30 KB` (since the max publish payload is `∼32 KiB`), none of the extra fields will be present. Instead there will be a `here_now_refresh` boolean field set to `true`. This indicates to the user that they should do a `hereNow` request to get the complete list of users present in the channel.

```json
{
    "channel": "my_channel",
    "subscription": null,
    "actualChannel": null,
    "subscribedChannel": "my_channel-pnpres",
    "action": "interval",
    "timetoken": "15119477396210903",
    "occupancy": 4,
    "timestamp": 1511947739,
    "here_now_refresh" : true
}
```

You can be notified of connectivity status, message, and presence notifications via the listeners.

Listeners should be added before calling the method.

#### Add listeners

```javascript
pubnub.addListener({
  // Messages
  message: function (m) {
    const channelName = m.channel; // Channel on which the message was published
    const channelGroup = m.subscription; // Channel group or wildcard subscription match (if exists)
    const pubTT = m.timetoken; // Publish timetoken
    const msg = m.message; // Message payload
    const publisher = m.publisher; // Message publisher
  },
  // Presence
  // requires a subscription with presence
  presence: function (p) {
    const action = p.action; // Can be join, leave, timeout, state-change, or interval
    const channelName = p.channel; // Channel to which the message belongs
    const occupancy = p.occupancy; // Number of users subscribed to the channel
    const state = p.state; // User state
    const channelGroup = p.subscription; //  Channel group or wildcard subscription match, if any
    const publishTime = p.timestamp; // Publish timetoken
    const timetoken = p.timetoken; // Current timetoken
    const uuid = p.uuid; // UUIDs of users who are subscribed to the channel
  },
  // Signals
  signal: function (s) {
    const channelName = s.channel; // Channel to which the signal belongs
    const channelGroup = s.subscription; // Channel group or wildcard subscription match, if any
    const pubTT = s.timetoken; // Publish timetoken
    const msg = s.message; // Payload
    const publisher = s.publisher; // Message publisher
  },
  // App Context
  objects: (objectEvent) => {
    const channel = objectEvent.channel; // Channel to which the event belongs
    const channelGroup = objectEvent.subscription; // Channel group
    const timetoken = objectEvent.timetoken; // Event timetoken
    const publisher = objectEvent.publisher; // UUID that made the call
    const event = objectEvent.event; // Name of the event that occurred
    const type = objectEvent.type; // Type of the event that occurred
    const data = objectEvent.data; // Data from the event that occurred
  },
  // Message Actions
  messageAction: function (ma) {
    const channelName = ma.channel; // Channel to which the message belongs
    const publisher = ma.publisher; // Message publisher
    const event = ma.event; // Message action added or removed
    const type = ma.data.type; // Message action type
    const value = ma.data.value; // Message action value
    const messageTimetoken = ma.data.messageTimetoken; // Timetoken of the original message
    const actionTimetoken = ma.data.actionTimetoken; // Timetoken of the message action
  },
  // File Sharing
  file: function (event) {
    const channelName = event.channel; // Channel to which the file belongs
    const channelGroup = event.subscription; // Channel group or wildcard subscription match (if exists)
    const publisher = event.publisher; // File publisher
    const timetoken = event.timetoken; // Event timetoken

    const message = event.message; // Optional message attached to the file
    const fileId = event.file.id; // File unique id
    const fileName = event.file.name;// File name
    const fileUrl = event.file.url; // File direct URL
  },
  status: function (s) {
    const affectedChannelGroups = s.affectedChannelGroups; // Array of channel groups affected in the operation
    const affectedChannels = s.affectedChannels; // Array of channels affected in the operation
    const category = s.category; // Returns PNConnectedCategory
    const operation = s.operation; // Returns PNSubscribeOperation
    const lastTimetoken = s.lastTimetoken; // Last timetoken used in the subscribe request (type long)
    const currentTimetoken = s.currentTimetoken; /* Current timetoken fetched in subscribe response,
                                                * to be used in the next request (type long) */
    const subscribedChannels = s.subscribedChannels; // Array of all currently subscribed channels
  },
});
```

#### Remove listeners

```javascript
var existingListener = {
  message: function () {
  },
};

pubnub.removeListener(existingListener);
```

##### Listener status events

| Category | Description |
| --- | --- |
| `PNNetworkUpCategory` | The SDK detected that the network is online. |
| `PNNetworkDownCategory` | The SDK announces this when a connection isn't available, or when the SDK isn't able to reach PubNub servers. |
| `PNNetworkIssuesCategory` | A subscribe event experienced an exception when running. The SDK isn't able to reach PubNub servers. This may be due to many reasons, such as the machine or device isn't connected to the internet; the internet connection has been lost; your internet service provider is having trouble; or, perhaps the SDK is behind a proxy. |
| `PNReconnectedCategory` | The SDK was able to reconnect to PubNub. |
| `PNConnectedCategory` | SDK subscribed with a new mix of channels. This is fired every time the channel or channel group mix changes. |
| `PNAccessDeniedCategory` | Access Manager permission failure. |
| `PNMalformedResponseCategory` | JSON parsing crashed. |
| `PNBadRequestCategory` | The server responded with a bad response error because the request is malformed. |
| `PNDecryptionErrorCategory` | If using decryption strategies and the decryption fails. |
| `PNTimeoutCategory` | Failure to establish a connection to PubNub due to a timeout. |
| `PNRequestMessageCountExceedCategory` | The SDK announces this error if `requestMessageCountThreshold` is set, and the number of messages received from PubNub (in-memory cache messages) exceeds the threshold. |
| `PNUnknownCategory` | Returned when the subscriber gets a non-200 HTTP response code from the server. |

## Unsubscribe (old)

:::warning Not recommended
The use of this method is discouraged. Use [Unsubscribe](#unsubscribe) instead.
:::

When subscribed to a single channel, this function causes the client to issue a `leave` from the `channel` and close any open socket to the PubNub Network. For multiplexed channels, the specified `channel`(s) will be removed and the socket remains open until there are no more channels remaining in the list.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

To `Unsubscribe from a channel`, you can use the following method(s) in the JavaScript SDK:

```javascript
pubnub.unsubscribe({
    channels: Array<string>,
    channelGroups: Array<string>
}): Promise<UnsubscribeResponse>;
```

| Parameter | Description |
| --- | --- |
| `channels` *Type: Array`<string>` | Specifies the `channel` ID to unsubscribe from. |
| `channelGroups`Type: Array`<string>` | Specifies the `channelGroups` to unsubscribe from. |

#### Sample code

Unsubscribe from a channel:

```javascript
pubnub.unsubscribe({
  channels: ['my_channel'],
});
```

#### Response

The output below demonstrates the response to a successful call:

```json
{
    "action" : "leave"
}
```

#### Other examples

##### Unsubscribing from multiple channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.unsubscribe({
  channels: ['chan1', 'chan2', 'chan3'],
});
```

###### Example response

```json
{
    "action" : "leave"
}
```

##### Unsubscribing from multiple channel groups

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```javascript
pubnub.unsubscribe({
  channelGroups: ['demo_group1', 'demo_group2'],
});
```

## Unsubscribe all (old)

:::warning Not recommended
The use of this method is discouraged. Use [Unsubscribe all](#unsubscribe-all) instead.
:::

Unsubscribe from all channels and all channel groups

#### Method(s)

```javascript
unsubscribeAll()
```

#### Sample code

```javascript
pubnub.unsubscribeAll();
```

#### Returns

None

## Terms in this document

* **Access Manager** - A cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and user IDs.
* **Action** - The type of activity (procedure) to execute when a condition is satisfied (for example, sending a message).
* **Billing alert notification** - A means of informing a user that a billing alert has been triggered. Before notifications can happen, a billing alert must be triggered first.
* **Business Object** - A container for data fields and metrics that defines aggregations and data sources.
* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Condition** - A requirement that must be satisfied or evaluated to true for an action to be executed. Input in a decision table.
* **Cryptor** - An implementation of a specific cryptographic algorithm used for data encryption/decryption that adheres to a standard interface.
* **Dashboard** - A collection of widgets (charts) that give an overview of the metrics one is evaluating.
* **Data fields** - Data you want Illuminate to track. These can be quantitative (measures), like "Number" or "Timestamp" or qualitative (dimensions) values, like "String" that can be used to categorize and segment data. Data fields can be aggregated and calculated.
* **Decision** - A collection (or decision table) of conditions and actions. When conditions are satisfied, the corresponding actions are triggered as per defined rules.
* **End Customer** - A customer of a PubNub partner. End customers do not have direct access to the Admin Portal. Instead, they interact with PubNub products—such as Illuminate—through the partner’s portal, where PubNub services are embedded. They can create PubNub objects only within this partner-provided environment.
* **Entity** - A subscribable object within a PubNub SDK that allows you to perform context-specific operations.
* **Listener** - A function or objectthat reacts to events or messages, like new chat messages or connection updates, letting your app respond in real-time.
* **Mapped/Unmapped** - Whether the data source for a data field has been defined or the action has been configured.
* **MCP Server** - A Model Context Protocol server that coordinates communication and synchronization between AI agents, clients, or services, such as Cursor IDE and Windsurf.
* **Message** - A unit of data transmitted between clients or between a client and a server in PubNub, containing information such as text, binary data, or structured data formats like JSON. Messages are sent over channels and can be tracked for delivery and read status.
* **Metric** - What exactly is evaluated using measures and dimensions (collectively called data fields), as well as aggregation functions.
* **Module** - A Functions v1 container that groups related functions for configuration and deployment on an app’s keysets.
* **Origin** - The subdomain used to establish a connection to the PubNub network that allows your application's traffic to appear like it's coming from your own domain.
* **Package** - A Functions v2 container that groups Functions, tracks Revisions, and is deployed to keysets.
* **Partner** - A PubNub customer who resells PubNub products, such as Illuminate, to their own customers. Partners have access to the Admin Portal, enabling them to create and manage PubNub objects for themselves or on behalf of their end customers.
* **Publish Key** - A unique identifier that allows your application to send messages to PubNub channels. It's part of your app's credentials and should be kept secure.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
* **Push token** - A device identifier issued by a push provider (APNs or FCM) used to register a device for receiving mobile push notifications.
* **Rule** - A definition (row in a decision table) stating which action should be triggered for which condition.
* **Service Integration** - A machine identity that represents a program or service consuming the Admin API, scoped to your account and authenticated using expirable API keys with configurable permissions.
* **Signal** - A non-persistent message limited to 64 bytes designed for high-volume usecases where the the most recent data is relevant, like GPS location updates.
* **Subscribe Key** - A unique identifier that allows your application to receive messages from PubNub channels. It's part of your app's credentials and should be kept secure.
* **Timetoken** - A unique identifier for each message that represents the number of 100-nanosecond intervals since January 1, 1970, for example, 16200000000000000.
* **Trigger details** - A set of predefined criteria for a given billing alert. When met, billing alert notifications are generated.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.
* **Vibe Coding** - A way to build applications in an intuitive, relaxed, and improvisational manner, using AI tools and natural language descriptions.