# Reactions

Stream Chat has built-in support for user Reactions. Common examples are likes, comments, loves, etc. Reactions can be customized so that you are able to use any type of reaction your application requires.

![](https://getstream.imgix.net/images/docs/send_reaction@2x.png?auto=compress&fit=clip&w=800&h=600)

Similar to other objects in Stream Chat, reactions allow you to add custom data to the reaction of your choice. This is helpful if you want to customize the reaction logic.

| name           | type    | description                                                                                   | default | optional |
| -------------- | ------- | --------------------------------------------------------------------------------------------- | ------- | -------- |
| message_id     | string  | ID of the message to react to                                                                 |         |          |
| reaction       | object  | Reaction object                                                                               |         |          |
| reaction.type  | string  | Type of the reaction. User could have only 1 reaction of each type per message                |         |          |
| reaction.score | integer | Score of the reaction for cumulative reactions (see example below)                            | 1       | ✓        |
| user_id        | string  | User ID for server side calls                                                                 |         | ✓        |
| enforce_unique | boolean | If set to true, new reaction will replace all reactions the user has (if any) on this message | false   | ✓        |
| skip_push      | boolean | Do not send a push notification                                                               | false   | ✓        |
| emoji_code     | string  | Accepts an unicode which is used by the backend to display the emoji in push notification     |         | ✓        |

<admonition type="warning">

Custom data for reactions is limited to 1KB.

</admonition>

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val channelClient = client.channel("messaging", "general")

// Add reaction 'like' with a custom field
val reaction = Reaction(
  messageId = "message-id",
  type = "like",
  score = 1,
  extraData = mutableMapOf("customField" to 1),
)
channelClient.sendReaction(reaction).enqueue { result ->
  if (result is Result.Success) {
    val sentReaction: Reaction = result.value
  } else {
    // Handle Result.Failure
  }
}

// Add reaction 'like' and replace all other reactions of this user by it
channelClient.sendReaction(reaction, enforceUnique = true).enqueue { result ->
  if (result is Result.Success) {
    val sentReaction: Reaction = result.value
  } else {
    // Handle Result.Failure
  }
}
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
// Add reaction 'love' with custom field, using emoji
const reaction = await channel.sendReaction(messageID, {
  type: "love",
  myCustomField: "💙",
});

// Add reaction 'love' from the server side
const reaction = await channel.sendReaction(messageID, {
  type: "love",
  user_id: userid,
});

// Add reaction 'like' and replace all other reactions of this user by it
const reaction = await channel.sendReaction(
  messageID,
  { type: "love", user_id: userid },
  { enforce_unique: true },
);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
import StreamChat

/// 1: Create a `ChannelId` that represents the channel you want to get a message from.
let channelId = ChannelId(type: .messaging, id: "general")

/// 2: Create a `MessageId` that represents the message you want to get.
let messageId = "message-id"

/// 3: Use the `ChatClient` to create a `ChatMessageController` with the `ChannelId` and message id.
let messageController = chatClient.messageController(cid: channelId, messageId: messageId)

/// 4: Call `ChatMessageController.addReaction` to add the reaction.
messageController.addReaction("like") { error in
  print(error ?? "message liked")
}
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $channel->sendReaction('message-id', ['type'=>'love','myCustomField'=>123], $userId);
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
await channel.sendReaction("messageID", "like", extraData: {"customField": 1});
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
channel.send_reaction(message_id, {"type": "love", "my_custom_field": 123}, user_id)
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
reaction := &stream_chat.Reaction{
	Type:   "love",
	ExtraData: map[string]interface{}{"my_custom_field": 123},
}
msg, err := channel.SendReaction(reaction, msgID, userID)
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
const FReaction Reaction = Channel->SendReaction(Message, TEXT("love"));
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
# require 'stream-chat'

channel.send_reaction(message_id, {type: "love", my_custom_field: 123}, user_id)
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
await reactionClient.SendReactionAsync(message.Id, "love", user.Id);
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
// Send simple reaction with a score of 1
await message.SendReactionAsync("like");

// Send reaction with a custom score value
await message.SendReactionAsync("clap", 10);

// Send reaction with a custom score value
await message.SendReactionAsync("clap", 10);

// Send reaction and replace all previous reactions (if any) from this user
await message.SendReactionAsync("love", enforceUnique: true);
```

</codetabs-item>

</codetabs>

### Removing a Reaction

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
channelClient.deleteReaction(
  messageId = "message-id",
  reactionType = "like",
).enqueue { result ->
  if (result is Result.Success) {
    val message: Message = result.value
  } else {
    // Handle Result.Failure
  }
}
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.deleteReaction(messageID, "love");
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
messageController.deleteReaction("like") { error in
  print(error ?? "like removed")
}
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
$response = $channel->deleteReaction('message-id','love', $userId);
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
await channel.deleteReaction("messageID", "like");
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
channel.delete_reaction(message_id, "love", user_id)
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
_, err := channel.DeleteReaction(msgID, "love", userID)
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Channel->DeleteReaction(Message, Reaction);
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
channel.delete_reaction(message_id, "love", user_id)
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
await reactionClient.DeleteReactionAsync(message.Id, "love", user.Id);
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
await message.DeleteReactionAsync("like");
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
// Android SDK
String reactionType = "like";
channelClient.deleteReaction("message-id", reactionType).enqueue(result -> {
  if (result.isSuccess()) {
    Message message = result.data();
  } else {
    // Handle result.error()
  }
});

// Backend SDK
Reaction.delete(message.getId(), reactionType)
  .userId(user.getId())
  .request());
```

</codetabs-item>

</codetabs>

### Retrieve Reactions

Reactions are being returned as a part of the Message object. Please refer to the [Message format](/chat/docs/<framework>/message_format/#messages-returned-by-the-api-follow-this-structure:/) section for more details.

### Paginating Reactions

Messages returned by the APIs automatically include the 10 most recent reactions. You can also retrieve more reactions and paginate using the following logic, consider that the maximum value for the Limit parameter is 300 and for the Offset parameter is 1000:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// Get the first 10 reactions
channelClient.getReactions(
  messageId = "message-id",
  offset = 0,
  limit = 10,
).enqueue { result ->
  if (result is Result.Success) {
    val reactions: List<Reaction> = result.value
  } else {
    // Handle Result.Failure
  }
}

// Get the second 10 reactions
channelClient.getReactions(
  messageId = "message-id",
  offset = 10,
  limit = 10,
).enqueue { /* ... */ }

// Get 10 reactions after particular reaction
channelClient.getReactions(
  messageId = "message-id",
  firstReactionId = "reaction-id",
  limit = 10,
).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
// get the first 10 reactions
const response = await channel.getReactions(messageID, { limit: 10 });

// get 3 reactions past the first 10
const response = await channel.getReactions(messageID, { limit: 3, offset: 10 });// Load 10 first reactions
messageController.loadReactions(limit: 10, offset: 0) { result in
  // …
  let loadedReactions = messageController.reactions
}
// Load 10 more reactions
messageController.loadNextReactions(limit: 10) { error in
  // …
  let loadedReactions = messageController.reactions
}
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// Load 10 first reactions
messageController.loadReactions(limit: 10, offset: 0) { result in
  // …
  let loadedReactions = messageController.reactions
}
// Load 10 more reactions
messageController.loadNextReactions(limit: 10) { error in
  // …
  let loadedReactions = messageController.reactions
}
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
// get the first 10 reactions
$response = $channel->getReactions('message-id',['limit' => 10]);

// get 3 reactions past the first 10
$response = $channel->getReactions('message-id',['limit' => 3, 'offset' => 10]);
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
// get the first 10 reactions
await channel.getReactions("messageID", PaginationParams(limit: 10));

// get 3 reactions past the first 10
await channel.getReactions("messageID", PaginationParams(limit: 3, offset:10));
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
# get the first 10 reactions
channel.get_reactions(message_id)

# get 3 reactions past the first 10
channel.get_reactions(message_id, limit=3, offset=10)
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
options := map[string][]string{
		"limit": {"10"},
		"idlte": {"10"},
	}

	_, err := channel.GetReactions(msgID, options)
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
// get the first 10 reactions
Channel->GetReactions(
  Message,
  {
    10,  // Limit
  });

// get 3 reactions past the first 10
Channel->GetReactions(
  Message,
  {
    3,   // Limit
    10,  // Offset
  });
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
# get the first 10 reactions
channel.get_reactions(message_id)

# get 3 reactions past the first 10
channel.get_reactions(message_id, limit: 3, offset: 10)
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// get the first 10 reactions
await reactionClient.GetReactionsAsync(message.Id);

// get 3 reactions past the first 10
await reactionClient.GetReactionsAsync(message.Id, offset: 10, limit: 3)
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
// Will be implemented soon, raise a GitHub issue if you need this feature https://github.com/GetStream/stream-chat-unity/issues/
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
// Android SDK

// Get the first 10 reactions
int offset = 0;
int limit = 10;
channelClient.getReactions("message-id", offset, limit).enqueue(result -> {
  if (result.isSuccess()) {
    List<Reaction> reactions = result.data();
  } else {
    // Handle result.error()
  }
});

// Get the second 10 reactions
offset = 10;
channelClient.getReactions("message-id", offset, limit)
   .enqueue(result -> { /* ... */ });

// Get 10 reactions after particular reaction
String reactionId = "reaction-id";
channelClient.getReactions("message-id", reactionId, limit)
    .enqueue(result -> { /* ... */ });


// Backend SDK
// get 3 reactions past the first 10
Reaction.list(messageId).limit(3).offset(10).request();
```

</codetabs-item>

</codetabs>

### Cumulative (Clap) Reactions

You can use the Reactions API to build something similar to Medium's clap reactions. If you are not familiar with this, Medium allows you to clap articles more than once and shows the sum of all claps from all users.

![](https://user-images.githubusercontent.com/88735/75765502-eb496500-5d3f-11ea-99ef-48e28ea13eb9.png)

To do this, you only need to include a score for the reaction (ie. user X clapped 25 times) and the API will return the sum of all reaction scores as well as each user's individual scores (ie. clapped 475 times, user Y clapped 14 times).

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val reaction = Reaction(messageId = "message-id", type = "clap", score = 5)
channelClient.sendReaction(reaction).enqueue { /* ... */ }
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
// user claps 5 times on a message
await channel.sendReaction(messageID, {
  type: "clap",
  score: 5,
});

// same user claps 20 times more
await channel.sendReaction(messageID, {
  type: "clap",
  score: 25,
});
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
// user claps 5 times on a message
await channel.sendReaction("messageID", "like", score: 5);

// same user claps 20 times more
await channel.sendReaction("messageID", "like", score: 25);
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
# user claps 5 times on a message
channel.send_reaction(message_id, {"type": "clap", "score": 5}, user_id)

# same user claps 20 times more
channel.send_reaction(message_id, {"type": "clap", "score": 25}, user_id)
```

</codetabs-item>

<codetabs-item value="php" label="PHP">

```php
// user claps 5 times on a message
$channel->sendReaction('message-id', ['type'=>'clap', 'score'=>5], $userId);

// same user claps 20 times more
$channel->sendReaction('message-id', ['type'=>'clap', 'score'=>25], $userId);
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
_, err = channel.SendReaction(&stream_chat.Reaction{
	Type: "clap", ExtraData: map[string]interface{}{"score": 25},
}, msgID, userID)
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
messageController.addReaction("clap", score: 2) { error in
  print(error ?? "message clapped twice")
}
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
// user claps 5 times on a message
Channel->SendReaction(Message, TEXT("like"), 5);

// same user claps 20 times more
Channel->SendReaction(Message, TEXT("like"), 20);
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
# user claps 5 times on a message
channel.send_reaction(message_id, {type: "clap", score: 5}, user_id)

# same user claps 20 times more
channel.send_reaction(message_id, {type: "clap", score: 25}, user_id)
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// user claps 5 times on a message
var reaction = new ReactionRequest { Type = "clap", UserId = user.Id, Score = 5 };
await reactionClient.SendReactionAsync(message.Id, reaction);

// same user claps 20 times more
var reaction = new ReactionRequest { Type = "clap", UserId = user.Id, Score = 25 };
await reactionClient.SendReactionAsync(message.Id, reaction);
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
await message.SendReactionAsync("clap", score: 3);
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
// Android SDK
Reaction reaction = new Reaction();
reaction.setMessageId("message-id");
reaction.setType("like");
reaction.setScore(5);

boolean enforceUnique = false;
channelClient.sendReaction(reaction, enforceUnique).enqueue(result -> { /* ... */ });

// Backend SDK
// Add reaction 'like' and replace all other reactions of this user by it
Reaction.send(messageId)
  .enforceUnique(true)
  .reaction(ReactionRequestObject.builder().type("like").score(5).userId(userId).build())
  .request();
```

</codetabs-item>

</codetabs>

### Query Reactions

This endpoint allow you to query reactions by filtering over type and user on a specific message id.

In case of this endpoint is used client side, the user need to have permission to read channel.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
const id = uuidv4();
await client.queryReactions(message.id, { type: "like" });
await client.queryReactions(message.id, { user_id: id });
```

</codetabs-item>

</codetabs>

Clearly it is possible to have different call for pagination:

- first call will fetch 25 reactions

- the second returns other 5 reactions starting from the latest of the first call

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
const data = await client.queryReactions(message.id, {});
const dataPage2 = await reactionClient.queryReactions(
  message.id,
  {},
  {},
  { limit: 5, next: data.next },
);
```

</codetabs-item>

</codetabs>

---

This page was last updated at 2025-08-15T14:15:08.921Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/react/send_reaction/](https://getstream.io/chat/docs/react/send_reaction/).