Gateways are Discord's form of real-time communication over secure websockets. Clients will receive events and data over the gateway they are connected to and send data over the REST API. For information about connecting to a gateway see the Connecting section. The API for interacting with Gateways is complex and fairly unforgiving, therefore its highly recommended you read all of the following documentation before writing a custom implementation.

Get Gateway

Returns an object with a single valid WSS URL, which the client can use as a basis for Connecting. Clients should cache this value and only call this endpoint to retrieve a new URL if they are unable to properly establish a connection using the cached version of the URL.
This endpoint does not require any authentication.
Example Response
    "url": "wss://"

Get Gateway Bot

Returns an object with the same information as Get Gateway, plus a shards key, containing the recommended number of shards to connect with (as an integer). Bots that want to dynamically/automatically spawn shard processes should use this endpoint to determine the number of processes to run. This route should be called once when starting up numerous shards, with the response being cached and passed to all sub-shards/processes. Unlike the Get Gateway, this route should not be cached for extended periods of time as the value is not guaranteed to be the same per-call, and changes as the bot joins/leaves guilds.
This endpoint requires authentication using a valid bot token.
Example Response
  "url": "wss://",
  "shards": 9

Gateway Protocol Versions

The Discord Gateway has a versioning system which is separate from the core APIs. The documentation herein is only for the latest version in the following table, unless otherwise specified.
Gateway versions below v6 will be discontinued on October 16, 2017.

Gateway Opcodes/Payloads

Gateway Payload Structure
opintegeropcode for the payloadAlways
d?mixed (object, integer, bool)event dataAlways
sintegersequence number, used for resuming sessions and heartbeatsOnly for Opcode 0
tstringthe event name for this payloadOnly for Opcode 0
Gateway Opcodes
CodeNameClient ActionDescription
0DispatchReceivedispatches an event
1HeartbeatSend/Receiveused for ping checking
2IdentifySendused for client handshake
3Status UpdateSendused to update the client status
4Voice State UpdateSendused to join/move/leave voice channels
5Voice Server PingSendused for voice ping checking
6ResumeSendused to resume a closed connection
7ReconnectReceiveused to tell clients to reconnect to the gateway
8Request Guild MembersSendused to request guild members
9Invalid SessionReceiveused to notify client they have an invalid session id
10HelloReceivesent immediately after connecting, contains heartbeat and server debug information
11Heartbeat ACKReceivesent immediately following a client heartbeat that was received

Gateway Dispatch

Used by the gateway to notify the client of events.
Example Gateway Dispatch
    "op": 0,
    "d": {},
    "s": 42,

Gateway Heartbeat

Used to maintain an active gateway connection. Must be sent every heartbeat_interval milliseconds after the Hello payload is received. Note that this interval already has room for error, and that client implementations do not need to send a heartbeat faster than what's specified. The inner d key must be set to the last seq (s) received by the client. If none has yet been received you should send null (you cannot send a heartbeat before authenticating, however).This OP code is also bidirectional. The gateway may request a heartbeat from you in some situations, and you should send a heartbeat back to the gateway as you normally would.
It is worth noting that in the event of a service outage where you stay connected to the gateway, you should continue to heartbeat and receive ACKs. The gateway will eventually respond and issue a session once it is able to.
Example Gateway Heartbeat
    "op": 1,
    "d": 251

Gateway Heartbeat ACK

Used for the client to maintain an active gateway connection. Sent by the server after receiving a Gateway Heartbeat
Example Gateway Heartbeat ACK
    "op": 11

Gateway Hello

Sent on connection to the websocket. Defines the heartbeat interval that the client should heartbeat to.
Gateway Hello Structure
heartbeat_intervalintegerthe interval (in milliseconds) the client should heartbeat with
_tracearray of stringsused for debugging, array of servers connected to
Example Gateway Hello
    "heartbeat_interval": 45000,
    "_trace": ["discord-gateway-prd-1-99"]

Gateway Identify

Used to trigger the initial handshake with the gateway.
Gateway Identify Structure
tokenstringauthentication token
propertiesobjectconnection properties
compressboolwhether this connection supports compression of packets
large_thresholdintegervalue between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list
shardarray of two integers (shard_id, num_shards)used for Guild Sharding
presencegateway status update objectpresence structure for initial presence information
Gateway Identify Connection Properties
$osstringyour operating system
$browserstringyour library name
$devicestringyour library name
Example Gateway Identify
    "token": "my_token",
    "properties": {
        "$os": "linux",
        "$browser": "disco",
        "$device": "disco"
    "compress": true,
    "large_threshold": 250,
    "shard": [1, 10],
    "presence": {
        "game": {
            "name": "Cards Against Humanity",
            "type": 0
        "status": "dnd",
        "since": 91879201,
        "afk": false

Gateway Reconnect

Used to tell clients to reconnect to the gateway. Clients should immediately reconnect, and use the resume payload on the gateway.

Gateway Request Guild Members

Used to request offline members for a guild. When initially connecting, the gateway will only send offline members if a guild has less than the large_threshold members (value in the Gateway Identify). If a client wishes to receive additional members, they need to explicitly request them via this operation. The server will send Guild Members Chunk events in response with up to 1000 members per chunk until all members that match the request have been sent.
Gateway Request Guild Members Structure
guild_idsnowflakeid of the guild to get offline members for
querystringstring that username starts with, or an empty string to return all members
limitintegermaximum number of members to send or 0 to request all members matched
Example Gateway Request Guild Members
    "guild_id": "41771983444115456",
    "query": "",
    "limit": 0

Gateway Resume

Used to replay missed events when a disconnected client resumes.
Gateway Resume Structure
tokenstringsession token
session_idstringsession id
seqintegerlast sequence number received
Example Gateway Resume
    "token": "randomstring",
    "session_id": "evenmorerandomstring",
    "seq": 1337

Gateway Status Update

Sent by the client to indicate a presence or status update.
Gateway Status Update Structure
since?integerunix time (in milliseconds) of when the client went idle, or null if the client is not idle
game?game objectnull, or the user's new activity
statusstringthe user's new status
afkboolwhether or not the client is afk
Status Types
dndDo Not Disturb
invisibleInvisible and shown as offline
Example Gateway Status Update
    "since": 91879201,
    "game": {
        "name": "Save the Oxford Comma",
        "type": 0
    "status": "online",
    "afk": false

Gateway Voice State Update

Sent when a client wants to join, move, or disconnect from a voice channel.
Gateway Voice State Update Structure
guild_idsnowflakeid of the guild
channel_id?snowflakeid of the voice channel client wants to join (null if disconnecting)
self_muteboolis the client muted
self_deafboolis the client deafened
Example Gateway Voice State Update
    "guild_id": "41771983423143937",
    "channel_id": "127121515262115840",
    "self_mute": false,
    "self_deaf": false

Gateway Invalid Session

Sent to indicate one of at least three different situations: - the gateway could not initialize a session after receiving an Opcode 2 Identify - the gateway could not resume a previous session after receiving an Opcode 6 Resume - the gateway has invalidated an active session and is requesting client actionThe inner d key is a boolean that indicates whether the session may be resumable. See Connecting and Resuming for more information.
Example Gateway Invalid Session
    "op": 9,
    "d": false


The first step in establishing connectivity to the gateway is requesting a valid websocket endpoint from the API. This can be done through either the Get Gateway or the Get Gateway Bot endpoints.With the resulting payload, you can now open a websocket connection to the "url" (or endpoint) specified. Generally, it is a good idea to explicitly pass the gateway version and encoding (see the url params table below) as URL parameters (e.g. from our example we may connect to wss:// connected, the client should immediately receive an Opcode 10 Hello payload, with information on the connection's heartbeat interval. The client should now begin sending Opcode 1 Heartbeat payloads every heartbeat_interval milliseconds, until the connection is eventually closed or terminated. Clients can detect zombied or failed connections by listening for Opcode 11 Heartbeat ACK. If a client does not receive a heartbeat ack between its attempts at sending heartbeats, it should immediately terminate the connection with a non 1000 close code, reconnect, and attempt to resume.Next, the client is expected to send an Opcode 2 Identify or Opcode 6 Resume payload. If the payload is valid, the gateway will respond with a Ready event after identifying or a Resumed event after resuming, and your client can be considered in a "connected" state. Clients are limited to 1 identify every 5 seconds; if they exceed this limit, the gateway will respond with an Opcode 9 Invalid Session. It is important to note that although the ready event contains a large portion of the required initial state, some information (such as guilds and their members) is asynchronously sent (see Guild Create event)
Clients are limited to 1000 IDENTIFY calls to the websocket in a 24-hour period. This limit is global and across all shards, but does not include RESUME calls. Upon hitting this limit, all active sessions for the bot will be terminated, the bot's token will be reset, and the owner will receive an email notification. It's up to the owner to update their application with the new token.
Gateway URL Params
vintegerGateway Version to use
encodingstring'json' or 'etf'


The internet is a scary place, and persistent connections can often experience issues which causes them to sever and disconnect. Due to Discord's architecture, this is a semi-regular event and should be expected. Because a large portion of a client's state must be thrown out and recomputed when a connection is opened, Discord has a process for "resuming" (or reconnecting) a connection without throwing away the previous state. This process is very similar to starting a fresh connection, and allows the client to replay any lost events from the last sequence number they received in the exact same way they would receive them normally.To utilize resuming, your client should store the session_id from the Ready, and the sequence number of the last event it received. When your client detects that the connection has been disconnected, through either the underlying socketing being closed or from a lack of Gateway Heartbeat ACK's it should completely close the connection and open a new one (following the same strategy as Connecting). Once the new connection has been opened, the client should send a Gateway Resume. If successful, the gateway will respond by replaying all missed events in order, finishing with a Resumed event to signal replay has finished, and all subsequent events are new. It's also possible that your client cannot reconnect in time to resume, in which case the client will receive a Opcode 9 Invalid Session and is expected to wait a random amount of time—between 1 and 5 seconds—then send a fresh Opcode 2 Identify.


If the gateway ever issues a disconnect to your client it will provide a close event code that you can use to properly handle the disconnection.
Gateway Close Event Codes
4000unknown errorWe're not sure what went wrong. Try reconnecting?
4001unknown opcodeYou sent an invalid Gateway opcode. Don't do that!
4002decode errorYou sent an invalid payload to us. Don't do that!
4003not authenticatedYou sent us a payload prior to identifying.
4004authentication failedThe account token sent with your identify payload is incorrect.
4005already authenticatedYou sent more than one identify payload. Don't do that!
4007invalid seqThe sequence sent when resuming the session was invalid. Reconnect and start a new session.
4008rate limitedWoah nelly! You're sending payloads to us too quickly. Slow it down!
4009session timeoutYour session timed out. Reconnect and start a new one.
4010invalid shardYou sent us an invalid shard when identifying.
4011sharding requiredThe session would have handled too many guilds - you are required to shard your connection in order to connect.


When initially creating and handshaking connections to the Gateway, a user can chose whether they wish to communicate over plain-text JSON or binary ETF. When using ETF, the client must not send compressed messages to the server. Note that Snowflake IDs are transmitted as 64-bit integers over ETF, but are transmitted as strings over JSON. See erlpack for an implementation example.

Rate Limiting

Unlike the HTTP API, the Gateway does not provide a method for forced back-off or cooldown, but instead implements a hard limit on the number of messages sent over a period of time. Currently, clients are allowed 120 events every 60 seconds, meaning you can send on average at a rate of up to 2 events per second. Clients who surpass this limit are immediately disconnected from the Gateway, and similarly to the HTTP API, repeat offenders will have their API access revoked. Clients are also limited to one gateway connection per 5 seconds. If you hit this limit, the Gateway will respond with an Opcode 9 Invalid Session.
Clients may only update their game status 5 times per minute.

Tracking State

Most of a client's state is provided during the initial Ready event and the Guild Create events that immediately follow. As objects are further created/updated/deleted, other events are sent to notify the client of these changes and to provide the new or updated data. To avoid excessive API calls, Discord expects clients to locally cache as many object states as possible, and to update them as gateway events are received.An example of state tracking can be found with member status caching. When initially connecting to the gateway, the client receives information regarding the online status of guild members (online, idle, dnd, offline). To keep this state updated, a client must track and parse Presence Update events as they are received, and apply the provided data to the cached member objects.

Guild (Un)availability

When connecting to the gateway as a bot user, guilds that the bot is a part of start out as unavailable. Unavailable simply means that the gateway is either connecting, is unable to connect to a guild, or has disconnected from a guild. Don't fret however! When a guild goes unavailable the gateway will automatically attempt to reconnect on your behalf. As far as a client is concerned there is no distinction between a truly unavailable guild (meaning that the node that the guild is running on is unavailable) or a guild that the client is trying to connect to. As such, guilds only exist in two states: available or unavailable.


As bots grow and are added to an increasing number of guilds, some developers may find it necessary to break or split portions of their bots operations into separate logical processes. As such, Discord gateways implement a method of user-controlled guild-sharding which allows for splitting events across a number of gateway connections. Guild sharding is entirely user controlled, and requires no state-sharing between separate connections to operate.To enable sharding on a connection, the user should send the shard array in the identify payload. The first item in this array should be the zero-based integer value of the current shard, while the second represents the total number of shards. DMs will only be sent to shard 0. To calculate what events will be sent to what shard, the following formula can be used:
(guild_id >> 22) % num_shards == shard_id
As an example, if you wanted to split the connection between three shards, you'd use the following values for shard for each connection: [0, 3], [1, 3], and [2, 3]. Note that only the first shard ([0, 3]) would receive DMs.


Sending Payloads

Packets sent from the client to the Gateway API are encapsulated within a gateway payload object and must have the proper opcode and data object set. The payload object can then be serialized in the format of choice (see ETF/JSON), and sent over the websocket. Payloads to the gateway are limited to a maximum of 4096 bytes sent, going over this will cause a connection termination with error code 4002.

Receiving Payloads

Receiving payloads with the Gateway API is slightly more complex than sending. When using the JSON encoding with compression enabled, the Gateway has the option of sending payloads as compressed JSON binaries using zlib, meaning your library must detect (see RFC1950 2.2) and decompress these payloads before attempting to parse them. The gateway does not implement a shared compression context between messages sent.

Event Names

Event names are in standard constant form, fully upper-cased and replacing all spaces with underscores. For instance, Channel Create would be CHANNEL_CREATE and Voice State Update would be VOICE_STATE_UPDATE. Within the following documentation they have been left in standard English form to aid in readability.



The ready event is dispatched when a client has completed the initial handshake with the gateway (for new sessions). The ready event can be the largest and most complex event the gateway will send, as it contains all the state required for a client to begin interacting with the rest of the platform.
Ready Event Fields
vintegergateway protocol version
useruser objectinformation about the user including email
private_channelsarray of DM channel objectsthe direct messages the user is in
guildsarray of Unavailable Guild objectsthe guilds the user is in
session_idstringused for resuming connections
_tracearray of stringsused for debugging - the guilds the user is in


The resumed event is dispatched when a client has sent a resume payload to the gateway (for resuming existing sessions).
Resumed Event Fields
_tracearray of stringsused for debugging - the guilds the user is in

Channel Create

Sent when a new channel is created, relevant to the current user. The inner payload is a DM channel or guild channel object.

Channel Update

Sent when a channel is updated. The inner payload is a guild channel object.

Channel Delete

Sent when a channel relevant to the current user is deleted. The inner payload is a DM or Guild channel object.

Channel Pins Update

Sent when a message is pinned or unpinned in a text channel. This is not sent when a pinned message is deleted.
Channel Pins Update Event Fields
channel_idsnowflakethe id of the channel
last_pin_timestamp?ISO8601 timestampthe time at which the most recent pinned message was pinned

Guild Create

This event can be sent in three different scenarios:
  1. When a user is initially connecting, to lazily load and backfill information for all unavailable guilds sent in the Ready event.
  2. When a Guild becomes available again to the client.
  3. When the current user joins a new Guild.
The inner payload is a guild object, with all the extra fields specified.

Guild Update

Sent when a guild is updated. The inner payload is a guild object.

Guild Delete

Sent when a guild becomes unavailable during a guild outage, or when the user leaves or is removed from a guild. The inner payload is an unavailable guild object. If the unavailable field is not set, the user was removed from the guild.

Guild Ban Add

Sent when a user is banned from a guild. The inner payload is a user object, with an extra guild_id key.

Guild Ban Remove

Sent when a user is unbanned from a guild. The inner payload is a user object, with an extra guild_id key.

Guild Emojis Update

Sent when a guild's emojis have been updated.
Guild Emojis Update Event Fields
guild_idsnowflakeid of the guild
emojisarrayarray of emojis

Guild Integrations Update

Sent when a guild integration is updated.
Guild Integrations Update Event Fields
guild_idsnowflakeid of the guild whose integrations were updated

Guild Member Add

Sent when a new user joins a guild. The inner payload is a guild member object with these extra fields:
Guild Member Add Extra Fields
guild_idsnowflakeid of the guild

Guild Member Remove

Sent when a user is removed from a guild (leave/kick/ban).
Guild Member Remove Event Fields
guild_idsnowflakethe id of the guild
usera user objectthe user who was removed

Guild Member Update

Sent when a guild member is updated.
Guild Member Update Event Fields
guild_idsnowflakethe id of the guild
rolesarray of snowflakesuser role ids
usera user objectthe user
nickstringnickname of the user in the guild

Guild Members Chunk

Sent in response to Gateway Request Guild Members.
Guild Members Chunk Event Fields
guild_idsnowflakethe id of the guild
membersarray of guild membersset of guild members

Guild Role Create

Sent when a guild role is created.
Guild Role Create Event Fields
guild_idsnowflakethe id of the guild
rolea role objectthe role created

Guild Role Update

Sent when a guild role is updated.
Guild Role Update Event Fields
guild_idsnowflakethe id of the guild
rolea role objectthe role updated

Guild Role Delete

Sent when a guild role is deleted.
Guild Role Delete Event Fields
guild_idsnowflakeid of the guild
role_idsnowflakeid of the role

Message Create

Sent when a message is created. The inner payload is a message object.

Message Update

Sent when a message is updated. The inner payload is a message object.
Unlike creates, message updates may contain only a subset of the full message object payload (but will always contain an id and channel_id).

Message Delete

Sent when a message is deleted.
Message Delete Event Fields
idsnowflakethe id of the message
channel_idsnowflakethe id of the channel

Message Delete Bulk

Sent when multiple messages are deleted at once.
Message Delete Bulk Event Fields
idsarray of snowflakesthe ids of the messages
channel_idsnowflakethe id of the channel

Message Reaction Add

Sent when a user adds a reaction to a message.
Message Reaction Add Event Fields
user_idsnowflakethe id of the user
channel_idsnowflakethe id of the channel
message_idsnowflakethe id of the message
emojian emoji objectthe emoji used to react

Message Reaction Remove

Sent when a user removes a reaction from a message.
Message Reaction Remove Event Fields
user_idsnowflakethe id of the user
channel_idsnowflakethe id of the channel
message_idsnowflakethe id of the message
emojian emoji objectthe emoji used to react

Message Reaction Remove All

Sent when a user explicitly removes all reactions from a message.
Message Reaction Remove All Event Fields
channel_idsnowflakethe id of the channel
message_idsnowflakethe id of the message

Presence Update

A user's presence is their current state on a guild. This event is sent when a user's presence is updated for a guild.
The user object within this event can be partial, the only field which must be sent is the id field, everything else is optional. Along with this limitation, no fields are required, and the types of the fields are not validated. Your client should expect any combination of fields and types within this event.
Presence Update Event Fields
useruser objectthe user presence is being updated for
rolesarray of snowflakesroles this user is in
game?game objectnull, or the user's current activity
guild_idsnowflakeid of the guild
statusstringeither "idle", "dnd", "online", or "offline"

Game Object

Game Structure
namestringthe game's nameAlways
typeintegersee Game TypesAlways
url?stringstream url, is validated when type is 1When type is 1
Game Types
0GamePlaying {name}"Playing Rocket League"
1StreamingStreaming {name}"Streaming Rocket League"
The streaming type currently only supports Twitch. Only urls will work.
Example Game
    "name": "Rocket League",
    "type": 1,
    "url": ""

Typing Start

Sent when a user starts typing in a channel.
Typing Start Event Fields
channel_idsnowflakeid of the channel
user_idsnowflakeid of the user
timestampintegerunix time (in seconds) of when the user started typing

User Update

Sent when properties about the user change. Inner payload is a user object.

Voice State Update

Sent when someone joins/leaves/moves voice channels. Inner payload is a voice state object.

Voice Server Update

Sent when a guild's voice server is updated. This is sent when initially connecting to voice, and when the current voice instance fails over to a new server.
Voice Server Update Event Fields
tokenstringvoice connection token
guild_idsnowflakethe guild this voice server update is for
endpointstringthe voice server host
Example Voice Server Update Payload
    "token": "my_token",
    "guild_id": "41771983423143937",
    "endpoint": ""

Webhooks Update

Sent when a guild channel's webhook is created, updated, or deleted.
Webhook Update Event Fields
guild_idsnowflakeid of the guild
channel_idsnowflakeid of the channel