RakNet
RakNet is a multiplayer networking library that manages connections and delivers messages over UDP. It adds features that UDP does not provide on its own, including retransmission of lost messages, delivery in order, and splitting large messages into smaller pieces.
Applications choose a delivery mode for each message. A message that must arrive can be sent reliably, while a time-sensitive update can use sequencing so that an older update does not replace a newer one. The original C++ library is available in the RakNet source archive.
Use in Bedrock Edition
In Bedrock Edition, RakNet handles the connection carrying Minecraft’s game data. Its job is to transport that data; the Bedrock game protocol defines what the data means, including login, world information, and player actions.
The two protocols have separate version numbers. The RakNet version is checked during the initial connection exchange, while the Bedrock protocol version determines which Minecraft packet formats the client and server understand.
NetherNet became the default transport for dedicated servers in 26.50. RakNet was marked as deprecated in Preview 26.60.22.
Protocol structure
RakNet traffic has two forms. Offline packets discover a server and negotiate a connection before normal message delivery begins. Connected packets travel inside frames, which carry the information needed to deliver their contents correctly.
| Layer | What it contains |
|---|---|
| UDP datagram | One message sent across the network. |
| RakNet frame set | A datagram sequence number and one or more frames. |
| RakNet frame | Delivery metadata and a payload, or one fragment of a larger payload. |
| Bedrock game-data payload | A batch of Minecraft packets, carried inside a RakNet frame. |
A frame set can hold several frames. Their delivery modes are recorded separately, so receiving one datagram does not mean that every frame in it must be handled in the same way.
Data types
Packet fields are read in the order shown in their tables. Fixed-width numbers occupy a set number of bytes; strings and packet bodies have a length that determines how much data follows.
Big-endian stores the most significant byte first. Little-endian stores it last. RakNet uses both: frame indices are little-endian, while frame body lengths are big-endian.
| Type | Size | Encoding or purpose |
|---|---|---|
| Byte | 1 byte | Unsigned 8-bit integer, from 0 to 255. |
| Boolean | 1 byte | Usually 0x00 for false and 0x01 for true. |
| Short | 2 bytes | Signed 16-bit integer, from −32,768 to 32,767. |
| Unsigned short | 2 bytes | Unsigned 16-bit integer, from 0 to 65,535. |
| Int / unsigned int | 4 bytes | Signed or unsigned 32-bit value, as specified by the field. |
| Long | 8 bytes | 64-bit value; signedness depends on its purpose. |
uint24le | 3 bytes | Unsigned 24-bit little-endian value, used by datagram and frame indices. |
| String | Variable | A 16-bit unsigned byte length, followed by that many string bytes. |
| Magic | 16 bytes | Fixed marker used by offline packets. |
| IPv4 address | 7 bytes | Version byte, four inverted address bytes, and a big-endian port. |
| IPv6 address | 29 bytes | Version byte, address family, port, flow information, IPv6 address, and scope ID. |
Magic is a fixed marker used to recognize offline RakNet messages. It is always the following 16 bytes:
00 ff ff 00 fe fe fe fe fd fd fd fd 12 34 56 78
An IPv4 address starts with a version byte of 4, followed by four inverted address bytes and a big-endian port. IPv6 starts with 6 and uses the longer layout described above.[1]
Common fields
| Field | Meaning |
|---|---|
| GUID | A 64-bit identifier used to distinguish RakNet peers. It is separate from a Minecraft account identifier. |
| Timestamp | A time value included in a request or response, often echoed to relate the reply to the original request. |
| MTU | Maximum transmission unit: the packet size negotiated for the connection. It limits how much data fits in a datagram. |
| Ordering channel | A separate stream for ordering messages. Order is maintained within a channel rather than across all traffic. |
Handshake sequence
The connection is established in two stages. First, the peers agree on the transport version and MTU. They then exchange connected messages to accept and confirm the session. C → S means client to server; S → C means server to client.
Opening the connection
- C → S — Open Connection Request 1: the client announces its RakNet version and sends a padded MTU probe.
- S → C — Open Connection Reply 1: the server returns its GUID and selected MTU. An unsupported version receives Incompatible Protocol instead.
- C → S — Open Connection Request 2: the client supplies its GUID, the server address, and the negotiated MTU.
- S → C — Open Connection Reply 2: the server confirms the settings and reports the client address it sees.
Confirming the session
- C → S — Connection Request: the client requests acceptance over the connected transport.
- S → C — Connection Request Accepted: the server accepts and returns address and timing information.
- C → S — New Incoming Connection: the client confirms receipt of that acceptance.
After this exchange, Bedrock continues with its game-protocol login. Server discovery is separate: an Unconnected Ping and Pong can exchange server-list information without opening a session.
Packets
Packet identifiers are hexadecimal. Fields are listed in serialization order after the packet ID. Optional security fields and internal-address counts can vary by implementation.[2]
Unconnected Ping
Packet ID: 0x01 / 0x02.
Asks a server to identify itself before a session is opened. The server echoes the supplied timestamp in its Pong, allowing the response to be matched to the request. 0x01 requests a normal reply; 0x02 requests one only if the server accepts incoming connections.
| Field | Type | Description |
|---|---|---|
| Time | Long | Client ping timestamp, echoed in the response. |
| Magic | Magic | Offline packet marker. |
| Client GUID | Long | Client identifier. |
Unconnected Pong
Packet ID: 0x1c.
Returns the server’s GUID and advertisement in response to an Unconnected Ping. Bedrock reads the advertisement to display server information before the player joins.
| Field | Type | Description |
|---|---|---|
| Time | Long | Original ping timestamp. |
| Server GUID | Long | Server identifier. |
| Magic | Magic | Offline packet marker. |
| Server ID string | String | Server advertisement and list information. |
Bedrock server advertisement
The Server ID string is a semicolon-separated advertisement. Common fields include the edition marker, server name (MOTD), Bedrock protocol and game versions, current and maximum player counts, server GUID, game mode, and port information. Its exact layout depends on the game version. These values describe the advertised server; they are not the RakNet handshake’s protocol version.
Connected Ping
Packet ID: 0x00.
Sends a timestamp over an established session to measure connection latency. Either peer may send it; it is commonly delivered unreliably.
| Field | Type | Description |
|---|---|---|
| Time | Long | Sender’s ping timestamp. |
Connected Pong
Packet ID: 0x03.
Answers a Connected Ping by returning the original ping timestamp and the responder’s own timestamp. The echoed value relates this response to a particular ping.
| Field | Type | Description |
|---|---|---|
| Ping time | Long | Timestamp from the incoming ping. |
| Pong time | Long | Responder’s timestamp. |
Open Connection Request 1
Packet ID: 0x05.
Starts connection negotiation. The client identifies its RakNet version and pads the datagram with zero bytes to probe a usable packet size. The padding is not a numeric MTU field.
| Field | Type | Description |
|---|---|---|
| Magic | Magic | Offline marker. |
| Protocol version | Byte | RakNet transport version requested by the client. |
| Padding | Zero bytes | Zero padding used to probe the path MTU. |
Open Connection Reply 1
Packet ID: 0x06.
Answers the first request with the server GUID, security setting, and selected MTU. If the RakNet version is unsupported, the server sends Incompatible Protocol instead.
| Field | Type | Description |
|---|---|---|
| Magic | Magic | Offline marker. |
| Server GUID | Long | Server identifier. |
| Use security | Boolean | Whether RakNet security negotiation is used. |
| Cookie | Int, conditional | Included when the security variant supplies a cookie. |
| MTU | Unsigned short | Selected MTU. |
Open Connection Request 2
Packet ID: 0x07.
Returns the negotiated MTU together with the server address and client GUID. Security-enabled variants also return the cookie supplied by the server.
| Field | Type | Description |
|---|---|---|
| Magic | Magic | Offline marker. |
| Cookie | Int, conditional | Returned when supplied by the server. |
| Has security challenge | Boolean, conditional | Present when security is enabled. |
| Server address | Address | Address used for the server connection. |
| MTU | Unsigned short | Negotiated size. |
| Client GUID | Long | Client identifier. |
Open Connection Reply 2
Packet ID: 0x08.
Confirms the peer connection and MTU. Its client-address field is the endpoint observed by the server, rather than an address copied from the client.
| Field | Type | Description |
|---|---|---|
| Magic | Magic | Offline marker. |
| Server GUID | Long | Server identifier. |
| Client address | Address | Client endpoint observed by the server. |
| MTU | Unsigned short | Confirmed size. |
| Encryption enabled | Boolean | Whether RakNet encryption is enabled. |
Connection Request
Packet ID: 0x09.
Requests acceptance after the offline negotiation. Unlike the two Open Connection requests, this message travels through RakNet’s connected framing layer.
| Field | Type | Description |
|---|---|---|
| GUID | Long | Client identifier. |
| Time | Long | Request timestamp. |
| Use security | Boolean | Security request indicator. |
Connection Request Accepted
Packet ID: 0x10.
Accepts the client’s request and returns its assigned system index, address information, and timestamps. The request timestamp matches the preceding Connection Request.
| Field | Type | Description |
|---|---|---|
| Client address | Address | Client endpoint. |
| System index | Unsigned short | Index assigned by the server. |
| Internal addresses | Address array | 10 entries in the documented layout. |
| Request time | Long | Timestamp from Connection Request. |
| Time | Long | Server acceptance timestamp. |
New Incoming Connection
Packet ID: 0x13.
Completes the exchange by confirming that the client received Connection Request Accepted. It supplies address and timing information to the server.
| Field | Type | Description |
|---|---|---|
| Server address | Address | Server endpoint. |
| Internal addresses | Address array | 20 entries in the documented Bedrock layout. |
| Incoming timestamp | Long | Connection timing value. |
| Server timestamp | Long | Server timing value. |
Disconnection Notification
Packet ID: 0x15.
Notifies the other peer that the sender is ending the session. The packet has no additional payload in this layout.
Incompatible Protocol
Packet ID: 0x19.
Rejects an unsupported RakNet transport version and reports the server’s version. This response concerns the RakNet handshake, not Bedrock’s separate game-protocol compatibility check.
| Field | Type | Description |
|---|---|---|
| Protocol | Byte | Protocol version advertised by the server. |
| Magic | Magic | Offline marker. |
| Server GUID | Long | Server identifier. |
Frame Set Packet
Packet ID: commonly 0x80–0x8d.
A frame set carries one or more frames between connected peers. It contains a datagram sequence number followed by the frames. A frame-set datagram is identified by:
(packet_id & 0x80) == 0x80 && (packet_id & 0x60) == 0
The second condition distinguishes frame sets from ACK and NACK packets.
| Datagram field | Type | Purpose |
|---|---|---|
| Packet ID / flags | Byte | Identifies the data-datagram form. |
| Sequence number | uint24le | Datagram-level number used by ACK/NACK records. |
| Frames | One or more frames | Continue parsing until the datagram payload is consumed. |
Frame structure
| Frame field | Type | Present when / purpose |
|---|---|---|
| Flags | Byte | Upper three bits select reliability; 0x10 indicates a split frame. |
| Body length | Unsigned short, big-endian | Length in bits, not bytes. |
| Reliable index | uint24le | Reliable modes; detects duplicate reliable messages. |
| Sequenced index | uint24le | Sequenced modes; identifies older updates. |
| Ordered index | uint24le | Ordered or sequenced modes that use an ordering channel. |
| Ordering channel | Byte | Associated ordering stream; up to 32 channels in the standard implementation. |
| Split count | Unsigned int | Total number of fragments; present only in split frames. |
| Split ID | Unsigned short | Split frames only: identifies the message being reassembled. |
| Split index | Unsigned int | Split frames only: this fragment’s position. |
| Body | ceil(bit_length / 8) bytes | Encapsulated payload or fragment. |
Reliable indices are present in modes 2, 3, and 4. Sequenced indices are present in modes 1 and 4. Ordering indices and channels are present in modes 1, 3, and 4. Split fields are included only when the split flag is set.
Fragmentation
When a message does not fit in one frame, it is split into fragments. Each fragment carries a split ID, a total fragment count, and its position within the message. The receiver groups matching fragments and reassembles their payloads before delivering the complete message.
The body-length field still describes this frame’s payload in bits. A value of 80 therefore describes 10 bytes, while a split count of 3 means three fragments, not three bytes.
Reliability types
Reliability, sequencing, and ordering answer different questions. Reliability controls whether missing data is resent. Sequencing prevents an older update from replacing a newer one. Ordering makes messages reach the application in send order within their channel.[3]
| ID | Mode | Reliable | Sequenced | Ordered |
|---|---|---|---|---|
| 0 | Unreliable | No | No | No |
| 1 | Unreliable sequenced | No | Yes | No |
| 2 | Reliable | Yes | No | No |
| 3 | Reliable ordered | Yes | No | Yes |
| 4 | Reliable sequenced | Yes | Yes | No |
| 5 | Unreliable with ACK receipt | No | No | No |
| 6 | Reliable with ACK receipt | Yes | No | No |
| 7 | Reliable ordered with ACK receipt | Yes | No | Yes |
Modes 5–7 add delivery receipts in the original library and are serialized as modes 0, 2, and 3, respectively.[4]
For example, if update B is newer than update A, sequenced delivery can discard A when it arrives after B. With reliable ordered delivery, B waits if an earlier message is missing. Reliable delivery without ordering can deliver B first and deliver A when it is recovered.
Game Packet
Packet ID: 0xfe.
Carries a batch of Bedrock game packets inside a RakNet frame. The batch’s compression, encryption, and individual packet formats are part of the Bedrock game protocol.
| Field | Type | Description |
|---|---|---|
| Body | Bytes | Batched Bedrock game-protocol data. |
NACK
Packet ID: 0xa0.
Reports frame-set datagrams that have not arrived. The sender uses these missing sequence numbers to retransmit reliable data when required. An unreliable payload is not made reliable by being listed in a NACK.
| Field | Type | Description |
|---|---|---|
| Record count | Unsigned short | Number of records that follow. |
| Is single | Boolean, per record | True selects one sequence number; false selects a range. |
| Sequence number | uint24le | Present for a single record. |
| Range start | uint24le | Present for a range; first datagram number. |
| Range end | uint24le | Present for a range; last datagram number. |
ACK
Packet ID: 0xc0.
Reports frame-set datagrams that were received. Acknowledgment refers to transport receipt; it does not mean that a Minecraft action has finished. The record format matches NACK and supports individual numbers or inclusive ranges.
| Field | Type | Description |
|---|---|---|
| Record count | Unsigned short | Number of records that follow. |
| Is single | Boolean, per record | True selects one sequence number; false selects a range. |
| Sequence number | uint24le | Present for a single record. |
| Range start | uint24le | Present for a range; first datagram number. |
| Range end | uint24le | Present for a range; last datagram number. |
Libraries
The original C++ library and independent implementations are listed below. Some target Bedrock or older Pocket Edition versions, while others provide general RakNet networking. Their supported protocol versions and features differ. License labels are summaries; the repository’s license file specifies the applicable terms.
| Name | Language | Description | License |
|---|---|---|---|
| go-raknet | Go | RakNet implementation used by Dragonfly. | MIT |
| NetrexMC RakNet | Rust | Asynchronous RakNet implementation. | Apache-2.0 |
| PieRakNet | Python | RakNet implementation for PieMC. | GPL-3.0 |
| Cloudburst Network | Java | Networking components for CloudburstMC projects. | Apache-2.0 |
| rak-net | Python | Implementation originally developed for Podrum. | GPL-2.0 |
| JRakNet | Java | Java RakNet protocol implementation. | MIT |
| netty-raknet | Java | RakNet support for Netty. | MIT |
| JRakLibPlus | Java | Server library derived from RakLib and JRakLib. | LGPL |
| RakLib | PHP | Lightweight RakNet server implementation. | GPL-3.0 |
| raknet | JavaScript | Node.js UDP networking library following RakNet. | MIT |
| PyRakLib | Python | Python port of RakLib. | GPL |
| rust-raknet | Rust | Rust RakNet implementation. | MIT |
| Baltica | TypeScript | Bedrock toolkit with a RakNet implementation. | See repository. |
| RakNet.Py | Python | Protocol version 5 implementation for older Pocket Edition versions. | GPL |
| LavishMC RakNet | C++ | Fork of the original implementation. | BSD |
| RakNet — original | C++ | Archived original library. | BSD-2-Clause |
References
- ↑ "RakNet protocol notes — types and addresses" - GolemOrg
- ↑ "MessageIdentifiers.h — built-in packet IDs" - Oculus VR
- ↑ "PacketPriority.h — reliability modes" - Oculus VR
- ↑ "ReliabilityLayer.cpp — frame serialization" - Oculus VR
