> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ably/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscribing to Messages

Clients subscribe to a channel to receive the messages published to it. Clients can subscribe to all messages, or only messages identified by specific names.

Subscribing is an operation that is only available to the realtime interface of Pub/Sub SDKs. This is because it requires establishing a persistent [connection](/docs/connect) to Ably in order to receive messages in realtime.

## Subscribe to all messages

Use the [`subscribe()`](/docs/api/realtime-sdk/channels#subscribe) method on a channel to receive any messages that are published to it.

The following is an example of subscribing to all messages on a channel:

<Code>
  ```realtime_javascript theme={null}
  const realtime = new Ably.Realtime('{{API_KEY}}');
  const channel = realtime.channels.get('my-channel');
  await channel.subscribe((message) => {
    console.log('Received:', message.data);
  });
  ```

  ```realtime_nodejs theme={null}
  const realtime = new Ably.Realtime('{{API_KEY}}');
  const channel = realtime.channels.get('my-channel');
  await channel.subscribe((message) => {
    console.log('Received:', message.data);
  });
  ```

  ```realtime_ruby theme={null}
  realtime = Ably::Realtime.new('{{API_KEY}}')
  channel = realtime.channels.get('my-channel')
  channel.subscribe do |message|
    puts "Received: #{message.data}"
  end
  ```

  ```realtime_python theme={null}
  realtime = AblyRealtime('{{API_KEY}}')
  channel = realtime.channels.get('my-channel')
  def listener(message):
    print('Received:', message.data)
  await channel.subscribe(listener)
  ```

  ```realtime_java theme={null}
  AblyRealtime realtime = new AblyRealtime("{{API_KEY}}");
  Channel channel = realtime.channels.get("my-channel");
  channel.subscribe(new MessageListener() {
      @Override
      public void onMessage(Message message) {
          System.out.println("Received: " + message.data);
      }
  });
  ```

  ```realtime_csharp theme={null}
  AblyRealtime realtime = new AblyRealtime("{{API_KEY}}");
  IRealtimeChannel channel = realtime.Channels.Get("my-channel");
  channel.Subscribe(message => {
      Console.WriteLine($"Received: {message.Data}");
  });
  ```

  ```realtime_swift theme={null}
  let realtime = ARTRealtime(key: "{{API_KEY}}")
  let channel = realtime.channels.get("my-channel")
  channel.subscribe { message in
      print("Received: \(message.data)")
  }
  ```

  ```realtime_go theme={null}
  realtime, _ := ably.NewRealtime(
    ably.WithKey("{{API_KEY}}"))
  channel := realtime.Channels.Get("my-channel")

  _, err = channel.SubscribeAll(context.Background(), func(msg *ably.Message) {
    fmt.Printf("Received: %v\n", msg.Data)
  })
  ```
</Code>

## Subscribe to specific message names

You can subscribe to only messages with specific names:

<Code>
  ```realtime_javascript theme={null}
  await channel.subscribe('temperature', (message) => {
    console.log('Temperature:', message.data);
  });
  ```

  ```realtime_nodejs theme={null}
  await channel.subscribe('temperature', (message) => {
    console.log('Temperature:', message.data);
  });
  ```

  ```realtime_java theme={null}
  channel.subscribe("temperature", new MessageListener() {
      @Override
      public void onMessage(Message message) {
          System.out.println("Temperature: " + message.data);
      }
  });
  ```

  ```realtime_csharp theme={null}
  channel.Subscribe("temperature", message =>
  {
      Console.WriteLine($"Temperature: {message.Data}");
  });
  ```

  ```realtime_ruby theme={null}
  channel.subscribe('temperature') do |message|
    puts "Temperature: #{message.data}"
  end
  ```

  ```realtime_python theme={null}
  def listener(message):
    print(f'Temperature: {message.data}')
  await channel.subscribe('temperature', listener)
  ```

  ```realtime_swift theme={null}
  channel.subscribe("temperature") { message in
      print("Temperature: \(message.data)")
  }
  ```

  ```realtime_go theme={null}
  _, err = channel.Subscribe(context.Background(), "temperature", func(msg *ably.Message) {
    fmt.Printf("Temperature: %v\n", msg.Data)
  })
  ```
</Code>

## Subscribe to multiple message names

You can register multiple listeners for different message names:

<Code>
  ```javascript theme={null}
  // Subscribe to temperature updates
  await channel.subscribe('temperature', (message) => {
    console.log('Temperature:', message.data);
  });

  // Subscribe to humidity updates
  await channel.subscribe('humidity', (message) => {
    console.log('Humidity:', message.data);
  });

  // Subscribe to all other messages
  await channel.subscribe((message) => {
    console.log('Other:', message.name, message.data);
  });
  ```
</Code>

## Unsubscribe from messages

You can unsubscribe from messages to stop receiving updates:

<Code>
  ```javascript theme={null}
  // Unsubscribe a specific listener
  const listener = (message) => {
    console.log('Received:', message.data);
  };
  await channel.subscribe(listener);

  // Later, unsubscribe
  channel.unsubscribe(listener);
  ```

  ```java theme={null}
  MessageListener listener = new MessageListener() {
      @Override
      public void onMessage(Message message) {
          System.out.println("Received: " + message.data);
      }
  };

  channel.subscribe(listener);

  // Later, unsubscribe
  channel.unsubscribe(listener);
  ```
</Code>

### Unsubscribe from specific message names

<Code>
  ```javascript theme={null}
  // Unsubscribe from temperature messages only
  channel.unsubscribe('temperature');

  // Unsubscribe from all messages
  channel.unsubscribe();
  ```
</Code>

## Working with message data

Messages contain several useful properties:

<Code>
  ```javascript theme={null}
  await channel.subscribe((message) => {
    console.log('Name:', message.name);           // Event name
    console.log('Data:', message.data);           // Message payload
    console.log('Client ID:', message.clientId);  // Publisher's client ID
    console.log('Timestamp:', message.timestamp); // When message was published
    console.log('ID:', message.id);               // Unique message ID
  });
  ```
</Code>

## Handling connection state

It's good practice to handle connection state changes:

<Code>
  ```javascript theme={null}
  realtime.connection.on('connected', () => {
    console.log('Connected to Ably');
  });

  realtime.connection.on('disconnected', () => {
    console.log('Disconnected from Ably');
  });

  realtime.connection.on('failed', (stateChange) => {
    console.error('Connection failed:', stateChange.reason);
  });
  ```
</Code>

## Handling channel state

Channels also have state that you can monitor:

<Code>
  ```javascript theme={null}
  channel.on('attached', () => {
    console.log('Channel attached');
  });

  channel.on('detached', () => {
    console.log('Channel detached');
  });

  channel.on('failed', (stateChange) => {
    console.error('Channel failed:', stateChange.reason);
  });
  ```
</Code>

## Automatic reattachment

If the connection is lost, the Ably SDK will automatically attempt to reconnect and reattach to channels. Messages published during the disconnection will be delivered once the connection is restored (up to 2 minutes of message history).

## Next steps

* Learn how to [publish messages](/docs/pubsub/channels/publish)
* Understand [message format](/docs/pubsub/messages/format) and metadata
* Explore [message history](/docs/pubsub/history)
* Learn about [connection states](/docs/connect/states)
