---
title: Chat
description: "Play 0x09, client → server."
---

`play` · `0x09` · **serverbound** (client → server)

Sends a chat `message` typed by the player (max 256 characters). It includes `timestamp`, `salt`, an optional `signature` from the player's chat session key, and the last-seen `acknowledged` bitset with `offset` and `checksum`. The server validates the signature and ordering, then broadcasts it as `PlayerChat`.

Sent by the client, read by the server. Listen for it with `client.on("Chat", (data) => …)` on the receiving side.

## Fields

| Field | Type | Notes |
|---|---|---|
| `message` | String |  |
| `timestamp` | Long |  |
| `salt` | Long |  |
| `signature` | Optional |  |
| `offset` | VarInt |  |
| `acknowledged` | Byte[] |  |
| `checksum` | UByte |  |

## Send it

```ts
// Client side: unsigned chat, accepted by servers that do not enforce secure chat.
await client.sendPacket("Chat", {
  message: "hello",
  timestamp: BigInt(Date.now()),
  salt: 0n,
  signature: null,
  offset: 0,
  acknowledged: Buffer.alloc(3),
  checksum: 0,
});
```

`signature` is the 256-byte message signature or `null` for unsigned chat. `offset` and `acknowledged` describe which earlier messages the client has seen. A server that `enforcesSecureChat` rejects unsigned messages. Server side: read `data.message` and broadcast it with `SystemChat` or `PlayerChat`.

Field aliases listed under Notes are accepted as alternative keys when writing.

Source: [`src/Core/Versions/776/Packets/play/serverbound/Chat.ts`](https://github.com/GDLev/mc-protocol/blob/master/src/Core/Versions/776/Packets/play/serverbound/Chat.ts)
