VMess Protocol

VMess is an encrypted transmission protocol that can serve as a bridge between the Xray client and server.


The current version number is 1.


Underlying Protocol

VMess is a TCP-based protocol where all data is transmitted over TCP.

User ID

An ID is equivalent to a UUIDopen in new tag, which is a 16-byte long random number. Its function is similar to a token. An ID looks like: de305d54-75b4-431b-adb2-eb6b9e546014, it is almost entirely random and can be generated using any UUID generator, such as this oneopen in new tag.

User ID can be specified in the configuration file.


Communication Process

VMess is a stateless protocol, which means that data can be transmitted directly between the client and the server without the need for a handshake. Each data transmission has no impact on other data transmissions before or after it.

When a VMess client initiates a request, the server checks whether the request comes from a legitimate client. If the validation passes, the server forwards the request and sends the obtained response back to the client.

VMess uses an asymmetric format, meaning that the requests sent by the client and the responses from the server use different formats.

Client Request

16 BytesX BytesRemaining
Authentication InformationInstruction PartData Part

Authentication Information

The authentication information is a 16-byte hash (hash) value, which is calculated as follows:

  • H = MD5
  • K = User ID (16 bytes)
  • M = UTC time accurate to seconds, with a random value of ±30 seconds from the current time (8 bytes, Big Endian)
  • Hash = HMAC(H, K, M)

Command Section

The instruction part is encrypted using AES-128-CFB.

  • Key: MD5(user ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
  • IV: MD5(X + X + X + X), X = []byte(time generated by authentication information) (8 bytes, Big Endian)
1 Byte16 Bytes16 Bytes1 Byte1 Byte4 bits4 bits1 Byte1 Byte2 Bytes1 ByteN BytesP Bytes4 Bytes
VersionData Encryption IVData Encryption KeyResponse Authentication ValueOptionsReservedEncryption MethodReservedCommandPortAddress TypeAddressRandom ValueChecksum

Options Opt Details: (When a bit is 1, it means the option is enabled)


of which:

  • Version Number Ver: Always 1;
  • Data Encryption IV: Random value;
  • Data Encryption Key: Random value;
  • Response Authentication V: Random value;
  • Option Opt:
    • S (0x01): Standard format data stream (recommended);
    • R (0x02): Client expects to reuse TCP connection (deprecated in Xray 2.23+);
      • This item only takes effect when S is enabled;
    • M (0x04): Enable metadata obfuscation (recommended);
      • This item only takes effect when S is enabled;
      • When this item is enabled, the client and server need to construct two Shake instances respectively, RequestMask = Shake (request data IV), ResponseMask = Shake (response data IV).
    • X: Reserved
  • Redundancy P: Random value added before checksum value;
  • Encryption Method: Specify the encryption method for the data part, and the optional values are:
    • 0x00: AES-128-CFB;
    • 0x01: No encryption;
    • 0x02: AES-128-GCM;
    • 0x03: ChaCha20-Poly1305;
  • Instruction Cmd:
    • 0x01: TCP data;
    • 0x02: UDP data;
  • Port Port: Integer port number in Big Endian format;
  • Address Type T:
    • 0x01: IPv4
    • 0x02: Domain name
    • 0x03: IPv6
  • Address A:
    • When T = 0x01, A is a 4-byte IPv4 address;
    • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
    • When T = 0x03, A is a 16-byte IPv6 address;
  • Check F: FNV1a hash of all content in the instruction except F.

Data Section

When Opt(S) is enabled, this format is used for the data section. The actual request data is divided into several small chunks, and each chunk has the following format. After the server verifies all the small chunks, it will be forwarded in the basic format.

2 BytesL Bytes
Length LData Packet

in which:

  • Length L: A big-endian integer with a maximum value of 2^14.
    • When Opt(M) is enabled, the value of L is equal to the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
  • Packet: A data packet encrypted by the specified encryption method.

Before the transmission is completed, the data packet must contain actual data, in addition to the length and authentication data. When the transmission is complete, the client must send an empty data packet, that is, L = 0 (unencrypted) or the length of the authentication data (encrypted), to indicate the end of the transmission.

The packets are formatted as follows, depending on the encryption method:

  • Unencrypted:   - L bytes: actual data;
  • AES-128-CFB: The entire data section is encrypted using AES-128-CFB.   - 4 bytes: FNV1a hash of actual data;   - L - 4 bytes: actual data;
  • AES-128-GCM: Key is the Key of the instruction section, IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: GCM authentication information
  • ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: Poly1305 authentication information

Server Response

The header data is encrypted using AES-128-CFB encryption. The IV is MD5 of the data encryption IV, and the Key is MD5 of the data encryption Key. The actual response data varies depending on the encryption settings.

1 Byte1 Byte1 Byte1 ByteM BytesRemaining Part
Response Authentication VOption OptCommand CmdCommand Length MCommand ContentActual Response Data

in which:

  • Response Authentication V: must match the response authentication V in the client request.
  • Option Opt:
    • 0x01: server prepares to reuse TCP connections (deprecated in Xray 2.23+).
  • Command Cmd:
    • 0x01: dynamic port command.
  • Actual response data:
    • If Opt(S) in the request is enabled, the standard format is used. Otherwise, the basic format is used.
    • Both formats are identical to the request data.
      • When Opt(M) is enabled, the value of length L is equal to the true value XOR Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().

Dynamic Port Instructions

1 Byte2 Bytes16 Bytes2 Bytes1 Byte1 Byte
ReservedPortUser IDAlterIDUser levelValidity period T

in which:

  • Port: Integer port number in Big Endian format
  • T: Number of minutes as integer value.

When the client receives a dynamic port command, the server opens a new port for communication. The client can then send data to the new port. After T minutes, the port will expire, and the client must use the main port to communicate again.


  • To ensure forward compatibility, the values of all reserved fields must be 0.