The Login state is reached when a client sends a Handshake with Next State = 2 (or 3 for transfer). During Login the server authenticates the player against the Mojang session servers (in online mode), optionally enables packet compression, optionally exchanges plugin-defined query payloads, and finally hands the client a GameProfile. The state ends when the client sends Login Acknowledged, at which point both sides switch to Configuration.
See Data Types for primitive encodings, Connection Lifecycle for the surrounding state diagram, and Text Component for the reason field of Disconnect.
| ID | Name | Direction |
|---|---|---|
0x00 |
Disconnect (Login) | Client-bound |
0x01 |
Hello (Encryption Request) | Client-bound |
0x02 |
Game Profile (Login Success) | Client-bound |
0x03 |
Login Compression (Set Compression) | Client-bound |
0x04 |
Custom Query (Login Plugin Request) | Client-bound |
0x05 |
Cookie Request | Client-bound |
0x00 |
Hello (Login Start) | Server-bound |
0x01 |
Key (Encryption Response) | Server-bound |
0x02 |
Custom Query Answer (Login Plugin Response) | Server-bound |
0x03 |
Login Acknowledged | Server-bound |
0x04 |
Cookie Response | Server-bound |
The Login state implements an asymmetric-key key-exchange that yields a shared 16-byte AES key, plus an out-of-band check against https://sessionserver.mojang.com that proves the joining client owns the Mojang account whose username it claims.
shouldAuthenticate flag.shouldAuthenticate was true, the server now computes a SHA-1 digest over serverId || sharedSecret || serverPublicKeyBytes (concatenated raw bytes), formats the digest as a signed big-integer two's-complement hexadecimal string (the famous "Notchian hash" — leading minus sign for negative digests, no zero-padding), and queries https://sessionserver.mojang.com/session/minecraft/hasJoined?username=<name>&serverId=<hash>. A 200 OK response carries the authoritative GameProfile (UUID + skin/cape properties); anything else means the client failed authentication and must be disconnected.GameProfile.If at any step the server needs to abort, it sends Disconnect (Login) with a Text Component describing the failure and closes the socket. Cookies (see Store Cookie) may be requested in the Login state with Cookie Request; this is most useful immediately after a Transfer-initiated reconnect.
Packet ID: 0x00 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Reason | JSON Text Component | The disconnect message shown on the client's "Disconnected" screen. Encoded as a JSON string (not as the binary NBT component used in Configuration/Play) because the client may not yet have a registry context to decode NBT. |
Semantics. Server-initiated termination of the Login state. The connection is closed immediately after sending. Equivalent in role to the Configuration/Play Disconnect but with a JSON-string payload.
Packet ID: 0x01 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Server ID | String (20) | A short ASCII identifier salted into the Mojang hasJoined hash. Vanilla servers send the empty string. |
| Public Key | Byte Array (VarInt-prefixed) | The server's RSA-1024 public key, in X.509 SubjectPublicKeyInfo DER form. |
| Verify Token | Byte Array (VarInt-prefixed) | A 4-byte random nonce. The client must echo it back (encrypted) in Key so the server can prove the response wasn't replayed. |
| Should Authenticate | Boolean | When true, the server will perform the Mojang session check after decrypting Key. When false, the server skips the session call (used by velocity-style forwarding). |
Semantics. Sent after Hello (Login Start) when the server is in online mode. After this packet the next expected serverbound packet is Key.
Packet ID: 0x02 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Game Profile | GameProfile | The authenticated profile: UUID (16 bytes), name (String, 16), and an array of (name, value, optional signature) properties. The textures property carries the player's skin/cape. See Data Types. |
Semantics. Terminal client-bound packet of the Login state. The server stops handling Login packets after sending it and waits for Login Acknowledged.
Packet ID: 0x03 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Threshold | VarInt | Minimum uncompressed packet size, in bytes, that triggers zlib compression. A value < 0 disables compression entirely. |
Semantics. When sent, both sides immediately switch to the compressed framing described in the Overview. Sent at most once per connection, and only before Game Profile.
Packet ID: 0x04 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Transaction ID | VarInt | Unique per outstanding query; the client must echo it in its Custom Query Answer. |
| Channel | Identifier | Namespaced channel identifying the plugin protocol. |
| Data | Byte Array (no length prefix; consumes the rest of the packet) | Plugin-defined payload. Maximum 1 048 576 bytes. |
Semantics. Lets the server query the client for plugin-defined information before authentication completes. Most commonly used by proxies for modern player-info forwarding.
Packet ID: 0x05 · State: Login · Bound To: Client
| Field | Type | Notes |
|---|---|---|
| Key | Identifier | The cookie key whose value the server wants. |
Semantics. Asks the client to return a previously-stored cookie (see Store Cookie). The client must reply with Cookie Response. Useful immediately after a Transfer so the new server can recover the previous server's session token.
Packet ID: 0x00 · State: Login · Bound To: Server
| Field | Type | Notes |
|---|---|---|
| Name | String (16) | Player username chosen for this session. Servers in online mode treat this as a claim to be verified by the Mojang session check. |
| Player UUID | UUID | The client-known UUID for this profile. In online mode it is overwritten by the authoritative UUID returned by Mojang; in offline mode the server typically derives the UUID from the username via UUID.nameUUIDFromBytes("OfflinePlayer:<name>"). |
Semantics. First packet of the Login state. Triggers the server to either send Hello (Encryption Request) (online mode) or skip straight to Login Compression followed by Game Profile (offline mode).
Packet ID: 0x01 · State: Login · Bound To: Server
| Field | Type | Notes |
|---|---|---|
| Shared Secret | Byte Array (VarInt-prefixed) | The 16-byte AES shared secret, RSA-encrypted with the server's public key from Hello (Encryption Request). |
| Verify Token | Byte Array (VarInt-prefixed) | The verify token the server sent, RSA-encrypted with the same key. The server compares the decrypted plaintext byte-for-byte to detect MITM/replay. |
Semantics. Concludes the encryption handshake. After receiving and validating it the server keys its AES/CFB8 cipher and either runs the Mojang session check or, if shouldAuthenticate was false, proceeds straight to Game Profile.
Packet ID: 0x02 · State: Login · Bound To: Server
| Field | Type | Notes |
|---|---|---|
| Transaction ID | VarInt | Echoes the ID from the corresponding Custom Query. |
| Successful | Boolean (encoded via Optional prefix) |
true if the client understood the channel and provides a payload below; false otherwise (the Data field is absent in that case). |
| Data | Byte Array (consumes rest of packet) | Plugin-defined response payload, present only when Successful is true. Maximum 1 048 576 bytes. |
Semantics. Sent in reply to a Custom Query. Multiple may be in flight; the server matches them by Transaction ID.
Packet ID: 0x03 · State: Login · Bound To: Server
This packet has no fields.
Semantics. Terminal server-bound packet of the Login state. On receipt the server switches its connection state to Configuration; the client must do the same immediately after sending. Sent by the client in response to Game Profile.
Packet ID: 0x04 · State: Login · Bound To: Server
| Field | Type | Notes |
|---|---|---|
| Key | Identifier | Echoes the key from the Cookie Request. |
| Payload | Optional Byte Array (VarInt-prefixed, max 5120 bytes) | The stored cookie value, or absent if the client has no value for that key. |
Semantics. Sent in reply to Cookie Request. The payload is opaque to the client — it merely echoes whatever a server previously stored with Store Cookie.