# Packet Catalog — Control States Complete packet tables for the small, fully-enumerable states: **Handshaking, Status, Login, Configuration**. > **Baseline:** 1.21.1 (protocol 773). Version deltas noted inline. > **Sources:** > - `minecraft-data/data/pc/1.21.1/protocol.json` — IDs and field types (machine-readable ground truth) > - ViaVersion `ClientboundLoginPackets.java`, `ServerboundLoginPackets.java` — enum ordinal cross-check > - ViaVersion `ClientboundConfigurationPackets1_20_2.java`, `1_20_5.java`, `ServerboundConfigurationPackets1_20_2.java`, `1_20_5.java` — version delta cross-check > - minecraft.wiki/w/Java_Edition_protocol/Packets — field names and semantic descriptions > > **See also:** [../03-handshake.md](../03-handshake.md) · [../04-status-ping.md](../04-status-ping.md) · [../05-login-encryption.md](../05-login-encryption.md) · [../06-configuration.md](../06-configuration.md) --- ## Handshaking State The handshaking state has **no clientbound packets**. There is exactly one modern serverbound packet; the legacy ping byte is a legacy artifact that predates the formal state machine. ### Serverbound | ID | Name | Direction | Field summary | |--------|------------------------|-----------|---------------| | `0x00` | Handshake | C→S | `protocolVersion` (VarInt), `serverHost` (String ≤255), `serverPort` (u16), `nextState` (VarInt: 1=Status, 2=Login, 3=Transfer¹) | | `0xFE` | Legacy Server List Ping | C→S | `payload` (u8, always `0x01`); pre-1.7 clients only — modern servers recognize and respond with legacy format² | ¹ `nextState=3` (Transfer) added in 1.20.5 (protocol 766). ² `0xFE` is outside the normal VarInt packet-ID space; servers detect it by the raw byte value. Source: `minecraft-data/data/pc/1.21.1/protocol.json` → `handshaking.toServer.types` mappings `{"0x00": "set_protocol", "0xfe": "legacy_server_list_ping"}`. --- ## Status State Two packets in each direction. IDs are stable since 1.7. ### Serverbound | ID | Name | Direction | Field summary | |--------|----------------|-----------|---------------| | `0x00` | Status Request | C→S | No fields; triggers Status Response | | `0x01` | Ping Request | C→S | `time` (i64, ms timestamp) | ### Clientbound | ID | Name | Direction | Field summary | |--------|-----------------|-----------|---------------| | `0x00` | Status Response | S→C | `response` (String; JSON with version, players, description, favicon) | | `0x01` | Pong Response | S→C | `time` (i64; echo of Ping Request's timestamp) | Source: `minecraft-data/data/pc/1.21.1/protocol.json` → `status.toServer` / `status.toClient` mappings. --- ## Login State Login was extended in **1.20.2** (Login Acknowledged) and **1.20.5** (Cookie Request/Response). ### Serverbound | ID | Name | Direction | Since | Field summary | |--------|------------------------|-----------|---------|---------------| | `0x00` | Login Start | C→S | 1.7 | `username` (String ≤16), `playerUUID` (UUID) | | `0x01` | Encryption Response | C→S | 1.7 | `sharedSecret` (ByteArray, VarInt-length-prefixed; RSA-encrypted), `verifyToken` (ByteArray, VarInt-length-prefixed; RSA-encrypted) | | `0x02` | Login Plugin Response | C→S | 1.13 | `messageId` (VarInt; echoes request), `data` (optional restBuffer; absent if unhandled) | | `0x03` | Login Acknowledged | C→S | 1.20.2 | No fields; transitions server to Configuration state | | `0x04` | Cookie Response | C→S | 1.20.5 | `key` (String; resource location), `value` (optional ByteArray ≤5120 bytes) | ### Clientbound | ID | Name | Direction | Since | Field summary | |--------|------------------------|-----------|---------|---------------| | `0x00` | Disconnect (Login) | S→C | 1.7 | `reason` (String; JSON text component) | | `0x01` | Encryption Request | S→C | 1.7 | `serverId` (String, always `""` in modern protocol¹), `publicKey` (ByteArray; DER-encoded RSA), `verifyToken` (ByteArray; random nonce), `shouldAuthenticate` (bool; false = offline-mode) | | `0x02` | Login Success | S→C | 1.7 | `uuid` (UUID), `username` (String ≤16), `properties` (Array of {name:String, value:String, signature:Optional\}), `strictErrorHandling` (bool; added 1.20.5²) | | `0x03` | Set Compression | S→C | 1.8 | `threshold` (VarInt; packets ≥ this size get compressed; −1 = disable) | | `0x04` | Login Plugin Request | S→C | 1.13 | `messageId` (VarInt; unique per request), `channel` (String; resource location), `data` (restBuffer; plugin-defined payload) | | `0x05` | Cookie Request (Login) | S→C | 1.20.5 | `cookie` (String; resource location key) | ¹ Server ID was used for session-server auth in very old versions; now always empty string. ² `strictErrorHandling` field added in 1.20.5 — older clients receive a shorter Login Success. Source: `minecraft-data/data/pc/1.21.1/protocol.json` → `login.toServer` / `login.toClient` mappings. ViaVersion cross-check: `ClientboundLoginPackets.java` ordinals 0–5 match; `ServerboundLoginPackets.java` ordinals 0–4 match. --- ## Configuration State **Added in 1.20.2 (protocol 764).** Not present in 1.20 or earlier. The Configuration state runs between Login Acknowledged and Finish Configuration. Its purpose: push registry data, feature flags, resource packs, and tags before the client enters Play. The state can be re-entered from Play (server sends `Start Configuration`). The packet set expanded again in **1.20.5 (protocol 766)**: Cookie, Transfer, Store Cookie, resource-pack split (push/pop vs. unified), Select Known Packs, Custom Report Details, Server Links were added, shifting most IDs. ### Serverbound | ID | Name | Direction | Since | Field summary | |--------|------------------------------|-----------|---------|---------------| | `0x00` | Client Information | C→S | 1.20.2 | `locale` (String ≤16), `viewDistance` (i8), `chatFlags` (VarInt), `chatColors` (bool), `skinParts` (u8 bitmask), `mainHand` (VarInt: 0=left,1=right), `enableTextFiltering` (bool), `allowServerListings` (bool) | | `0x01` | Cookie Response | C→S | 1.20.5 | `key` (String; resource location), `value` (optional ByteArray ≤5120 bytes) | | `0x02` | Plugin Message | C→S | 1.20.2 | `channel` (String; resource location), `data` (restBuffer; `minecraft:brand` → UTF-8 VarInt-prefixed client brand string) | | `0x03` | Acknowledge Finish Configuration | C→S | 1.20.2 | No fields; transitions to Play state | | `0x04` | Keep Alive | C→S | 1.20.2 | `keepAliveId` (i64; echoes server's value) | | `0x05` | Pong | C→S | 1.20.2 | `id` (i32; echoes server's Ping id) | | `0x06` | Resource Pack Response | C→S | 1.20.2 | `uuid` (UUID; 1.20.5+¹), `result` (VarInt: 0=Success,1=Declined,2=Failed,3=Accepted,4=Downloaded,5=InvalidUrl,6=FailedReload,7=Discarded) | | `0x07` | Select Known Packs | C→S | 1.20.5 | `packs` (Array of {namespace:String, id:String, version:String}) | | `0x08` | Custom Report Details | C→S | 1.21 | `details` (Array of {key:String, value:String}; debug crash info)² | | `0x09` | Server Links Response | C→S | 1.21 | `links` (Array; echoes known-type or custom-text link list)² | ¹ In 1.20.2–1.20.4 the resource pack response had no UUID field; UUID was added when resource-pack-push/pop split was introduced in 1.20.5. ² IDs `0x08` and `0x09` are present in 1.21.1 per `protocol.json` (`custom_report_details`, `server_links`) but absent from earlier ViaVersion 1.20.5 enum — confirm exact introduction version. **ID shift note (1.20.2 → 1.20.5 serverbound):** | ID (1.20.2) | Name | ID (1.20.5+) | |-------------|------------------|--------------| | `0x00` | Client Information | `0x00` (no change) | | `0x01` | Plugin Message | `0x02` (+1) | | `0x02` | Finish Configuration | `0x03` (+1) | | `0x03` | Keep Alive | `0x04` (+1) | | `0x04` | Pong | `0x05` (+1) | | `0x05` | Resource Pack | `0x06` (+1) | | — | Cookie Response | `0x01` (new) | | — | Select Known Packs | `0x07` (new) | Source: `minecraft-data/data/pc/1.21.1/protocol.json` → `configuration.toServer`; `ViaVersion/.../ServerboundConfigurationPackets1_20_2.java` vs `ServerboundConfigurationPackets1_20_5.java`. --- ### Clientbound | ID | Name | Direction | Since | Field summary | |--------|------------------------|-----------|---------|---------------| | `0x00` | Cookie Request | S→C | 1.20.5 | `cookie` (String; resource location key to retrieve) | | `0x01` | Plugin Message | S→C | 1.20.2 | `channel` (String), `data` (restBuffer; `minecraft:brand` sends server brand) | | `0x02` | Disconnect | S→C | 1.20.2 | `reason` (anonymousNbt; text component as NBT, not JSON string) | | `0x03` | Finish Configuration | S→C | 1.20.2 | No fields; server signals config complete, waits for SB Acknowledge | | `0x04` | Keep Alive | S→C | 1.20.2 | `keepAliveId` (i64; client must echo within ~30s or be kicked) | | `0x05` | Ping | S→C | 1.20.2 | `id` (i32; client echoes in Pong) | | `0x06` | Reset Chat | S→C | 1.20.2 | No fields; clears client chat session state | | `0x07` | Registry Data | S→C | 1.20.2 | `id` (String; registry resource location), `entries` (Array of {key:String, value:Optional\}); one packet per registry | | `0x08` | Remove Resource Pack | S→C | 1.20.5 | `uuid` (optional UUID; absent = remove all) | | `0x09` | Add Resource Pack | S→C | 1.20.5 | `uuid` (UUID), `url` (String), `hash` (String, SHA-1 hex), `forced` (bool), `promptMessage` (Optional\ text component) | | `0x0A` | Store Cookie | S→C | 1.20.5 | `key` (String; resource location), `value` (ByteArray ≤5120 bytes) | | `0x0B` | Transfer | S→C | 1.20.5 | `host` (String), `port` (VarInt); redirects client to another server | | `0x0C` | Feature Flags | S→C | 1.20.2 | `features` (Array\; resource location list of active experimental features) | | `0x0D` | Update Tags | S→C | 1.20.2 | `tags` (Array of {tagType:String, tags:Array of {tagName:String, entries:Array\}}) | | `0x0E` | Select Known Packs | S→C | 1.20.5 | `packs` (Array of {namespace:String, id:String, version:String}); client replies SB Select Known Packs | | `0x0F` | Custom Report Details | S→C | 1.21 | `details` (Array of {key:String, value:String}); appears in crash reports¹ | | `0x10` | Server Links | S→C | 1.21 | `links` (Array of {hasKnownType:bool, knownType:ServerLinkType (if known), unknownType:NbtComponent (if custom), url:String})¹ | ¹ `0x0F` and `0x10` present in 1.21.1 `protocol.json`; not in ViaVersion 1.20.5 CB enum (15 entries, 0x00–0x0E). Likely introduced 1.21.0 or 1.21.1. **ID shift note (1.20.2 → 1.20.5 clientbound):** | ID (1.20.2) | Name | ID (1.20.5+) | |-------------|-------------------|--------------| | `0x00` | Plugin Message | `0x01` (+1) | | `0x01` | Disconnect | `0x02` (+1) | | `0x02` | Finish Configuration | `0x03` (+1) | | `0x03` | Keep Alive | `0x04` (+1) | | `0x04` | Ping | `0x05` (+1) | | `0x05` | Registry Data | `0x07` (+2) | | `0x06` | Resource Pack | split: `0x08`/`0x09` | | `0x07` | Feature Flags | `0x0C` (+5) | | `0x08` | Update Tags | `0x0D` (+5) | | — | Cookie Request | `0x00` (new) | | — | Reset Chat | `0x06` (new) | | — | Store Cookie | `0x0A` (new) | | — | Transfer | `0x0B` (new) | | — | Select Known Packs | `0x0E` (new) | Source: `minecraft-data/data/pc/1.21.1/protocol.json` → `configuration.toClient`; `ViaVersion/.../ClientboundConfigurationPackets1_20_2.java` vs `ClientboundConfigurationPackets1_20_5.java`.