![]() |
VOOZH | about |
RakNet[1] is a networking library used by Bedrock Edition. This documentation is based on the old Pocket Edition protocol and may be incomplete or outdated. The source code for the RakNet Library can be found here. RakNet uses UDP as its networking protocol. The key differences from TCP are that not all packets are guaranteed to reach the destination at all or in order (it isn't reliable) and it uses messages with a specified length instead of streams of data. RakNet compensates for the out-of-order delivery and makes it reliable.
NOTE: You may want to use an existing library if one exists for your language of choice. Here is an incomplete list. Not all of these are maintained or complete. If these are outdated you may need to change the protocol version to 11 before it can work. The protocol doesn't seem to have had any significant changes since the official implementation was discontinued in 2014, so as long as you bump the protocol version older libraries are likely to still work.
| Name | Description | Language | License | Active development |
|---|---|---|---|---|
| go-raknet | Network System used for Dragonfly written in Go. | Golang | MIT | Yes |
| RakNet | RakNet implementation written in Rust. | Rust | Apache License | No |
| PieRakNet | Network System used for PieMC written in Python. | Python | GPL-3 | Yes |
| NukkitX Network | Network components used within NukkitX, but with great support for general use as well. | Java | Apache License | Yes |
| rak-net | rak-net is the first updated and fully working RakNet implementation written in Python to run a Minecraft Bedrock Edition server. This library was mainly created for Podrum, although it can be used in other projects too and can be installed via pip. | Python | GPL | No |
| JRakNet | JRakNet is a networking library for Java which implements the UDP based protocol RakNet. | Java | MIT | No |
| netty-raknet | High performance implementation of RakNet for netty, following strict netty patterns. | Java | MIT | No |
| JRakLibPlus | A library for easy creation of RakNet servers, based on RakLib and JRakLib. | Java | LGPL | No |
| RakLib | RakNet server implementation written in PHP. This library is very lightweight on actual implementation - it provides the bare minimum to get a Minecraft Pocket Edition server functional. It only currently provides server functionality, and does not support most RakNet features. | PHP | GPL | Yes |
| raknet | UDP network library that follows the RakNet protocol for Node.js. | Javascript | MIT | No |
| PyRakLib | PyRakLib is a networking library that follows the RakNet protocol for MCPE. It is ported from the PHP library RakLib. | Python | GPL | No |
| rust-raknet | RakNet Protocol implementation by Rust. | Rust | MIT | No |
| Baltica | Baltica is a toolkit for Minecraft Bedrock Edition that includes packages for Xbox authentication and RakNet protocol implementation. | TypeScript | None | Yes |
| RakNet.Py | Mojang RakNet Protocol version 5 implementation in Python intended for use with MCPE Alpha versions. | Python | GPL | No |
| LavishRakNet | Custom implementation of RakNet made for game client and server. | C++ | MIT | Yes |
| Raknet (official) | The official implementation. Outdated and mostly for reference purposes. May not work with the latest Bedrock. | C++ | BSD | No |
| Size (Bytes) | Range | Notes | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| byte | 1 | 0 to 255 |
A single byte, also called uchar or uint8 | ||||||||||||||||||||||||||||||||||||||||||||
| Long | 8 | -2^63 to 2^63-1 | Signed 64-bit Integer, also called int64 | ||||||||||||||||||||||||||||||||||||||||||||
| Magic | 16 | 00ffff00fefefefefdfdfdfd12345678
|
Always those hex bytes, corresponding to RakNet's default OFFLINE_MESSAGE_DATA_ID | ||||||||||||||||||||||||||||||||||||||||||||
| short | 2 | -32768 to 32767 | Signed 16-bit integer, also called int16 | ||||||||||||||||||||||||||||||||||||||||||||
| unsigned short | 2 | 0 to 65535 | Unsigned 16-bit integer, also called uint16 | ||||||||||||||||||||||||||||||||||||||||||||
| string | unsigned short + string | N/A | Prefixed by a uint16 containing the length of the string in characters, encoded in network byte order (see below). It appears that only the following ASCII characters can be displayed: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ | ||||||||||||||||||||||||||||||||||||||||||||
| boolean | 1 | 0 to 1 | True is encoded as 0x01, false as 0x00.
| ||||||||||||||||||||||||||||||||||||||||||||
| address | 7 or 29 | N/A | If the address is IPv4:
Else, if the address is IPv6:
Note: The IPv4 format is 7 bytes long, IPv6 is 29 bytes long. | ||||||||||||||||||||||||||||||||||||||||||||
| uint24le | 3 | 0 to 16,777,215 | 3-byte little-endian unsigned integer | ||||||||||||||||||||||||||||||||||||||||||||
| Int | 4 | -2147483648 to 2147483647 | Signed little-endian 32-bit Integer, also called int32 |
Note that some types and fields are encoded in network byte order (big-endian, see wikipedia), and decoding them in the wrong way could cause unexpected behaviour.
From here on, the RakNet connection is established and all RakNet messages are contained in a Frame Set Packet.
Next packets should be Game Packets.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x01, 0x02 | Time | Long | |
| MAGIC | magic | ||
| Client GUID | Long |
This is the first RakNet message sent by the client to a RakNet server. 0x01 is sent almost every second if the client is on the server list menu and every 4-5 seconds if the client is in-game.
0x02 is only replied to if there are open connections to the server. Note: as of 0.15.6 it seems that the game refreshes it's LAN world list every 4-5 seconds, however it seems the game will still ping in 1 second intervals.
This packet should be responded to with unconnected Pong.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x1c | Time | Long | |
| Server GUID | Long | ||
| MAGIC | magic | ||
| Server ID String | string | Used for the MOTD. See below for details. |
Unconnected Pong message is sent by the server to the client in response to the Unconnected Ping message. Time shall be set to the time received in the Unconnected Ping as it will probably be used to calculate ping. The Server ID String contains various data that is sent to the client such as MOTD, number of players, max player count, etc. The format is given below:
Server ID string format
For Minecraft Bedrock this is separated by semicolons and uses the following format:
Edition (MCPE or MCEE for Education Edition);MOTD line 1;Protocol Version;Version Name;Player Count;Max Player Count;Server Unique ID;MOTD line 2;Game mode;Game mode (numeric);Port (IPv4);Port (IPv6);
Example:
MCPE;Dedicated Server;390;1.14.60;0;10;13253860892328930865;Bedrock level;Survival;1;19132;19133;
Result:
๐ Image
The Game mode and Game mode (numeric) values seem to not be used by the client.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x00 | Time | Long |
This is the first packet sent in the Encapsulated Frame Set Packet by the client to the server. It is sent with the reliability type Unreliable so it can be handled immediately by the server. It is used for calculating the average ping between the client and the server.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x03 | Ping Time | Long | |
| Pong Time | Long |
Connected Pong message is sent in response to the Connected Ping message with reliability type set to Unreliable so it can be handled immediately by the client.
The first packet in the handshake sequence, sent by the client to the server.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x05 | Magic | MAGIC | |
| Protocol version | byte | Currently 11 | |
| MTU | Zero padding | The MTU sent in the response appears to be somewhere around the size of this padding + 46 (28 udp overhead, 1 packet id, 16 magic, 1 protocol version). This padding seems to be used to discover the maximum packet size the network can handle. |
The client sends these to the target server with ever decreasing MTU until the server responds. This is used to discover the MTU size for the connection. According to the official docs, "The MTU size is the maximum size of a packet RakNet will generate", and "if you set the MTU size larger than your or any router along the network path takes, then the network will split the packet at best, or drop it at worst", so this process of sending decreasingly padded packets (compensating for the size of the packet itself and UDP overhead, which together make 46 bytes) seem to be used to discover the maximum packet size the network can handle. See the official documentation page for more info about the MTU size. If the RakNet protocol does not match your own, respond with the Incompatible protocol packet.
You should always respond to the first of these packets that you receive with Open Connection Reply 1, containing an MTU size of the amount of padding you received in bytes plus 46.
The second packet in the handshake sequence, sent by the server to the client.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x06 | Magic | MAGIC | |
| Server GUID | Long | ||
| Use security | boolean | If true, a cookie can be specified after to prevent source IP spoofing | |
| Cookie | Int | Only if use security; a cookie to be sent back by the client in Open Connection Request 2 | |
| MTU | Unsigned short | see Open Connection Request 1 |
The third packet in the handshake sequence, sent by the client to the server.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x07 | Magic | MAGIC | |
| Cookie | Int | Only present if a cookie was provided by the server in Open Connection Reply 1 | |
| Has security challenge | boolean | Only present if a cookie was provided by the server in Open Connection Reply 1 | |
| Server Address | address | ||
| MTU | short | ||
| Client GUID | Long |
The fourth packet in the handshake sequence, sent by the server to the client.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x08 | Magic | MAGIC | |
| Server GUID | Long | ||
| Client Address | address | ||
| MTU | short | ||
| Encryption enabled | boolean |
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x09 | GUID | Long | |
| Time | Long | ||
| Use security | boolean |
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x10 | Client address | address | |
| System index | short | Unknown what this does. 0 works as a value. | |
| Internal IDs | 10x address | Unknown what these do. 255.255.255.255:19132 for all of them seems to work, any other address will probably work as well. | |
| Request time | Long | Shall be the corresponding timestamp of the Connection Request | |
| Time | Long | Current send time in milliseconds |
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x13 | Server address | address | |
| Internal address | 20x address | Unknown what this is used for. | |
| Incoming Timestamp | Long | ||
| Server Timestamp | Long |
| Packet ID |
|---|
| 0x15 |
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x19 | Protocol | byte | |
| Magic | MAGIC | ||
| Server GUID | Long |
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x01, 0x02 | Time | Long | |
| GUID | Long |
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0x80..0x8d | Sequence number | uint24le | Used for building ACK and NACK ranges | ||
| Frames | Flags | byte | Top 3 bits give the reliability type, fourth bit is 1 when the frame is fragmented and part of a compound. | ||
| Length IN BITS | unsigned short | Length of the body in bits. Big-endian. | |||
| Reliable frame index | uint24le | Only if reliable, used for detecting frame level duplication | |||
| Sequenced frame index | uint24le | Only if sequenced, used for discarding out-of-date packets | |||
| Order (only if ordered, see below) |
Ordered frame index | uint24le | Tells the receiver the correct order in which to deliver frames to the application | ||
| Order channel | byte | Maximum of 32 channels | |||
| Fragment (only if fragmented) |
Compound size | int | Total size of the compound | ||
| Compound ID | short | Identifies which compound this fragment is part of | |||
| Index | int | Index of this fragment in the compound | |||
| Body | ceil(length/8) bytes | ||||
Note 1: there can be multiple frames in each Frame Set Packet.
Note 2: A packet is a Frame Set Packet if (packet_ID & 0x80) == 0x80 and (packet_ID & 0x60) == 0
The reliability types are as follows:
| ID | Name | Reliable | Ordered | Sequenced |
|---|---|---|---|---|
| 0 | unreliable | |||
| 1 | unreliable sequenced | x | x | |
| 2 | reliable | x | ||
| 3 | reliable ordered | x | x | |
| 4 | reliable sequenced | x | x | x |
| 5 | unreliable (+ ACK receipt) | |||
| 6 | reliable (+ ACK receipt) | x | ||
| 7 | reliable ordered (+ ACK receipt) | x | x |
Sequenced implies ordered.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0xfe | Body | bytes | Single packet of the GAME protocol. The packet is usually compressed. |
In Minecraft Bedrock Edition, the game packet contains bytes encoded according to the Bedrock Edition Protocol.
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0xa0 | Record count | short | Number of records in the packet | ||
| Records | Is Single? | boolean | False for range, True for no range | ||
No Range, if is_single == true
|
Sequence number | uint24le | Sequence number to acknowledge | ||
Range, if is_single == false
|
Start Sequence number | uint24le | Beginning of the range | ||
| End Sequence number | uint24le | End of the range | |||
A NACK is sent by either the client or the server periodically to request packets that were not received. They are sent back only if they were marked with reliable (see Frame Set Packet).
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0xc0 | Record count | short | Number of records in the packet | ||
| Records | Is Single? | boolean | False for range, True for no range | ||
No Range, if is_single == true
|
Sequence number | uint24le | Sequence number to acknowledge | ||
Range, if is_single == false
|
Start Sequence number | uint24le | Beginning of the range | ||
| End Sequence number | uint24le | End of the range | |||
An ACK sould be sent periodically to acknowledge every packet that was received.
Note: for both ACK and NACK packets, there can be multiple records.