Skip to main content
RPC is currently in a private beta. Discord is not accepting new developers into the program at this time.
All Discord clients have an RPC server running on localhost that allows control over local Discord clients. The RPC server supports both WebSocket connections and HTTP proxy requests to the Discord API.

RPC Versions

VersionOut of Service
1no

Restrictions

Access to the RPC server is limited while developing. You may invite up to 50 approved testers while your app is unapproved. Unapproved apps are limited to creating 10 guilds and 10 channels. After approval, these limits are raised to virtually unlimited.

Payloads

All RPC payloads share a common structure:
FieldTypeDescriptionPresent
cmdenumRPC commandAlways
noncestringUnique string used once for replies from the serverIn responses to commands (not subscribed events)
evtenumSubscription eventIn subscribed events, errors, and (un)subscribing events
dataobjectEvent dataIn responses from the server
argsobjectCommand argumentsIn commands sent to the server

Connecting

The local RPC server runs on 127.0.0.1. WebSocket connections use:
ws://127.0.0.1:PORT/?v=VERSION&client_id=CLIENT_ID&encoding=ENCODING
  • CLIENT_ID — the client ID of your application
  • VERSION — the RPC server version (currently 1)
  • PORT — the RPC server port (see below)
  • ENCODINGjson or etf

RPC Server Ports

The RPC server picks a port from the range 6463–6472 sequentially. Your client should iterate over these ports until a successful connection is made. Track the successful port for the rest of the session.
The RPC server verifies the Origin header on WebSocket connection to prevent client ID spoofing. You will be instantly disconnected if the origin does not match your registered origins. Set your RPC Origin in the Developer Portal.
For non-browser apps (like games), ensure the origin is sent with the WebSocket upgrade request. Use https://localhost for local testing or your company/game’s domain for production.

Authenticating

All RPC commands require authentication. Unauthenticated calls return a 4006 error. The two-step authentication process uses AUTHORIZE followed by AUTHENTICATE.

Step 1: AUTHORIZE

Send an AUTHORIZE command to prompt the user to grant your app access. The response returns a code that can be exchanged for an access token.
{
  "nonce": "f48f6176-4afb-4c03-b1b8-d960861f5216",
  "args": {
    "client_id": "192741864418312192",
    "scopes": ["rpc", "identify"]
  },
  "cmd": "AUTHORIZE"
}
Response:
{
  "cmd": "AUTHORIZE",
  "data": {
    "code": "O62Q9JzFe8BEOUzIfsAndOjNd2V4sJ"
  },
  "nonce": "f48f6176-4afb-4c03-b1b8-d960861f5216"
}
Exchange the code with a POST to https://discord.com/api/oauth2/token using the standard OAuth2 token exchange parameters. Authorize Argument Structure
FieldTypeDescription
scopesarray of stringsOAuth2 scopes to authorize
client_idstringOAuth2 application ID
rpc_tokenstringOne-time use RPC token (for approved apps/testers)
usernamestringUsername to create a guest account with if the user does not have Discord

Step 2: AUTHENTICATE

Exchange the OAuth2 access token for an authenticated RPC session:
{
  "nonce": "5bb10a43-1fdc-4391-9512-0c8f4aa203d4",
  "args": {
    "access_token": "CZhtkLDpNYXgPH9Ml6shqh2OwykChw"
  },
  "cmd": "AUTHENTICATE"
}
Response:
{
  "cmd": "AUTHENTICATE",
  "data": {
    "application": {
      "description": "test app description",
      "icon": "d6b51c21c48482d5b64aa4832d92fe14",
      "id": "192741864418312192",
      "rpc_origins": ["http://localhost:3344"],
      "name": "test app"
    },
    "expires": "2017-06-29T19:09:52.361000+00:00",
    "user": {
      "username": "test user",
      "discriminator": "7479",
      "id": "190320984123768832",
      "avatar": "b004ec1740a63ca06ae2e14c5cee11f3"
    },
    "scopes": ["rpc", "identify"]
  },
  "nonce": "5bb10a43-1fdc-4391-9512-0c8f4aa203d4"
}
Authenticate Response Structure
FieldTypeDescription
userobjectThe authenticated user (partial)
scopesarrayAuthorized OAuth2 scopes
expiresdateExpiration date of OAuth2 token
applicationobjectThe application the user authorized

Commands and Events

RPC Commands

NameDescription
DISPATCHEvent dispatch
AUTHORIZEAuthorize a new client with your app
AUTHENTICATEAuthenticate an existing client with your app
GET_GUILDRetrieve guild information from the client
GET_GUILDSRetrieve a list of guilds from the client
GET_CHANNELRetrieve channel information from the client
GET_CHANNELSRetrieve a list of channels for a guild from the client
SUBSCRIBESubscribe to an RPC event
UNSUBSCRIBEUnsubscribe from an RPC event
SET_USER_VOICE_SETTINGSChange voice settings of users in voice channels
SELECT_VOICE_CHANNELJoin or leave a voice channel, group DM, or DM
GET_SELECTED_VOICE_CHANNELGet the current voice channel the client is in
SELECT_TEXT_CHANNELJoin or leave a text channel, group DM, or DM
GET_VOICE_SETTINGSRetrieve the client’s voice settings
SET_VOICE_SETTINGSSet the client’s voice settings
SET_CERTIFIED_DEVICESSend info about certified hardware devices
SET_ACTIVITYUpdate a user’s Rich Presence
SEND_ACTIVITY_JOIN_INVITEConsent to a Rich Presence Ask to Join request
CLOSE_ACTIVITY_REQUESTReject a Rich Presence Ask to Join request

RPC Events

NameDescription
READYNon-subscription event sent immediately after connecting, contains server information
ERRORNon-subscription event sent when there is an error, including command responses
GUILD_STATUSSent when a subscribed server’s state changes
GUILD_CREATESent when a guild is created/joined on the client
CHANNEL_CREATESent when a channel is created/joined on the client
VOICE_CHANNEL_SELECTSent when the client joins a voice channel
VOICE_STATE_CREATESent when a user joins a subscribed voice channel
VOICE_STATE_UPDATESent when a user’s voice state changes in a subscribed voice channel (mute, volume, etc.)
VOICE_STATE_DELETESent when a user parts a subscribed voice channel
VOICE_SETTINGS_UPDATESent when the client’s voice settings update
VOICE_CONNECTION_STATUSSent when the client’s voice connection status changes
SPEAKING_STARTSent when a user in a subscribed voice channel speaks
SPEAKING_STOPSent when a user in a subscribed voice channel stops speaking
MESSAGE_CREATESent when a message is created in a subscribed text channel
MESSAGE_UPDATESent when a message is updated in a subscribed text channel
MESSAGE_DELETESent when a message is deleted in a subscribed text channel
NOTIFICATION_CREATESent when the client receives a notification (mention or new message in eligible channels)
ACTIVITY_JOINSent when the user clicks a Rich Presence join invite in chat to join a game
ACTIVITY_SPECTATESent when the user clicks a Rich Presence spectate invite in chat to spectate a game
ACTIVITY_JOIN_REQUESTSent when the user receives a Rich Presence Ask to Join request

Command Reference

Used to get a list of guilds the client is in.Request
{
  "nonce": "e16fcbed-8bfa-4fd4-ba09-73b72e809833",
  "args": {},
  "cmd": "GET_GUILDS"
}
Response
{
  "cmd": "GET_GUILDS",
  "data": {
    "guilds": [
      {
        "id": "199737254929760256",
        "name": "test"
      }
    ]
  },
  "nonce": "e16fcbed-8bfa-4fd4-ba09-73b72e809833"
}
Used to get a specific guild the client is in.Argument Structure
FieldTypeDescription
guild_idstringID of the guild to get
timeoutintegerAsynchronously get guild with time to wait before timing out
Response Structure
FieldTypeDescription
idstringGuild ID
namestringGuild name
icon_urlstringGuild icon URL
membersarray of objectsGuild members (deprecated; always returns an empty array)
Example
{
  "nonce": "9524922c-3d32-413a-bdaa-0804f4332588",
  "args": { "guild_id": "199737254929760256" },
  "cmd": "GET_GUILD"
}
Used to get a specific channel the client is in.Argument Structure
FieldTypeDescription
channel_idstringID of the channel to get
Response Structure
FieldTypeDescription
idstringChannel ID
guild_idstringChannel’s guild ID
namestringChannel name
typeintegerChannel type (guild text: 0, guild voice: 2, dm: 1, group dm: 3)
topicstring(text) Channel topic
bitrateinteger(voice) Bitrate of voice channel
user_limitinteger(voice) User limit of voice channel (0 for none)
positionintegerPosition of channel in channel list
voice_statesarray of objects(voice) Channel’s voice states
messagesarray of objects(text) Channel’s messages
Used to get a guild’s channels.Argument Structure
FieldTypeDescription
guild_idstringID of the guild to get channels for
Example
{
  "nonce": "0dee7bd4-8f62-4ecc-9e0f-1b1839a4fa93",
  "args": { "guild_id": "199737254929760256" },
  "cmd": "GET_CHANNELS"
}
Used to change voice settings of a specific user in a voice channel.
Only one app may modify voice settings at a time. When an app changes voice settings, it locks them so other apps lose the ability to change them. Settings reset when the controlling app disconnects.
Argument and Response Structure
FieldTypeDescription
user_idstringUser ID
pan?objectPan settings { left: float, right: float } (0.0–1.0)
volume?integerVolume (defaults to 100, min 0, max 200)
mute?booleanMute state
Example
{
  "nonce": "eafc8152-2248-4478-9827-8457b7900cb4",
  "args": {
    "user_id": "192731515703001088",
    "pan": { "left": 1.0, "right": 1.0 },
    "volume": 120,
    "mute": false
  },
  "cmd": "SET_USER_VOICE_SETTINGS"
}
Used to join or leave a voice channel, group DM, or DM. Returns the Get Channel response, or null if leaving.Argument Structure
FieldTypeDescription
channel_idstringChannel ID to join (or null to leave)
timeoutintegerAsynchronously join channel with time to wait before timing out
forcebooleanForce move a user to a voice channel
navigatebooleanNavigate to the channel in the client after joining
You will receive a 5003 error if the user is already in a voice channel. The force parameter should only be used after the user has explicitly approved being moved by your app.
Used to join or leave a text channel, group DM, or DM. Returns the Get Channel response, or null if leaving.Argument Structure
FieldTypeDescription
channel_idstringChannel ID to join (or null to leave)
timeoutintegerAsynchronously join channel with time to wait before timing out
GET_VOICE_SETTINGS retrieves the current voice settings. SET_VOICE_SETTINGS updates them — all fields are optional and only passed fields are updated.
Only one app may modify voice settings at a time (same restriction as SET_USER_VOICE_SETTINGS).
Voice Settings Structure
FieldTypeDescription
inputobjectInput device settings
outputobjectOutput device settings
modeobjectVoice mode settings
automatic_gain_controlbooleanState of automatic gain control
echo_cancellationbooleanState of echo cancellation
noise_suppressionbooleanState of noise suppression
qosbooleanState of voice quality of service
silence_warningbooleanState of silence warning notice
deafbooleanState of self-deafen
mutebooleanState of self-mute
Voice Settings Input/Output Object
FieldTypeDescription
device_idstringDevice ID
volumefloatInput voice level (0–100) / Output voice level (0–200)
available_devicesarray of objectsRead-only device objects with id and name string keys
Voice Settings Mode Object
FieldTypeDescription
typestringVoice mode: PUSH_TO_TALK or VOICE_ACTIVITY
auto_thresholdbooleanWhether voice activity threshold sets itself automatically
thresholdfloatThreshold for voice activity in dB (min: -100, max: 0)
shortcutobjectPush-to-talk shortcut key combo
delayfloatPTT release delay in ms (min: 0, max: 2000)
Key Types
TypeID
KEYBOARD_KEY0
MOUSE_BUTTON1
KEYBOARD_MODIFIER_KEY2
GAMEPAD_BUTTON3
Example: Set Voice Settings
{
  "nonce": "3d64ed55-ef6e-4bd5-99c9-677533babc22",
  "args": {
    "input": { "volume": 90.5 }
  },
  "cmd": "SET_VOICE_SETTINGS"
}
Used to subscribe or unsubscribe from RPC events. Set evt to the event name and args to the arguments required by that event.Subscribe Example
{
  "nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015",
  "args": { "guild_id": "199737254929760256" },
  "evt": "GUILD_STATUS",
  "cmd": "SUBSCRIBE"
}
Unsubscribe Example
{
  "nonce": "647d814a-4cf8-4fbb-948f-898aad24f55b",
  "args": { "guild_id": "199737254929760256" },
  "evt": "GUILD_STATUS",
  "cmd": "UNSUBSCRIBE"
}
Used by hardware manufacturers to send information about connected certified devices. See Certified Devices for the full integration guide.Argument Structure
FieldTypeDescription
devicesarray of objectsA list of devices for your manufacturer, in order of priority
Example
{
  "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
  "cmd": "SET_CERTIFIED_DEVICES",
  "args": {
    "devices": [
      {
        "type": "audioinput",
        "id": "aafc2003-da0e-42a3-b982-6a17a2812510",
        "vendor": {
          "name": "SteelSeries",
          "url": "https://steelseries.com"
        },
        "model": {
          "name": "Arctis 7",
          "url": "https://steelseries.com/gaming-headsets/arctis-7"
        },
        "related": ["aafc2003-da0e-42a3-b982-6a17a2819999"],
        "echo_cancellation": true,
        "noise_suppression": true,
        "automatic_gain_control": true,
        "hardware_mute": false
      }
    ]
  }
}
Used to update a user’s Rich Presence.
When using SET_ACTIVITY, the activity object is limited to a type of Playing (0), Listening (2), Watching (3), or Competing (5).
Argument Structure
FieldTypeDescription
pidintegerThe application’s process ID
activityobjectThe Rich Presence to assign to the user
Used to accept or reject a Rich Presence Ask to Join request.Argument Structure (both commands)
FieldTypeDescription
user_idsnowflakeThe ID of the requesting user
Example: Accept join request
{
  "nonce": "5dc0c062-98c6-47a0-8922-15aerg126",
  "cmd": "SEND_ACTIVITY_JOIN_INVITE",
  "args": { "user_id": "53908232506183680" }
}

Event Reference

Sent immediately after connecting. Contains the RPC version, server configuration, and the current user.
{
  "cmd": "DISPATCH",
  "data": {
    "v": 1,
    "config": {
      "cdn_host": "cdn.discordapp.com",
      "api_endpoint": "//discord.com/api",
      "environment": "production"
    },
    "user": {
      "id": "53908232506183680",
      "username": "Mason",
      "discriminator": "1337",
      "avatar": null
    }
  },
  "evt": "READY"
}
Sent when an error occurs, including failed command responses.
{
  "cmd": "AUTHORIZE",
  "data": {
    "code": 4007,
    "message": "No client id provided"
  },
  "evt": "ERROR",
  "nonce": "5102b6f0-c769-4f37-8cca-25fb0ab22628"
}
See RPC Error Codes for the full list.
Sent when a subscribed server’s state changes. Requires subscribing with a guild_id argument.
{
  "cmd": "DISPATCH",
  "data": {
    "guild": {
      "id": "199737254929760256",
      "name": "test",
      "icon_url": null
    },
    "online": 0
  },
  "evt": "GUILD_STATUS"
}
Dispatched when a user joins, changes state in, or leaves a subscribed voice channel. Requires subscribing with a channel_id argument.
{
  "cmd": "DISPATCH",
  "evt": "VOICE_STATE_CREATE",
  "data": {
    "voice_state": {
      "mute": false,
      "deaf": false,
      "self_mute": false,
      "self_deaf": false,
      "suppress": false
    },
    "user": {
      "id": "190320984123768832",
      "username": "test 2",
      "discriminator": "7479",
      "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
      "bot": false
    },
    "nick": "test user 2",
    "volume": 110,
    "mute": false,
    "pan": { "left": 1.0, "right": 1.0 }
  }
}
Sent when the client’s voice connection status changes.Dispatch Data Structure
FieldTypeDescription
statestringOne of the voice connection states listed below
hostnamestringHostname of the connected voice server
pingsarray of integersLast 20 pings (in ms)
average_pingintegerAverage ping (in ms)
last_pingintegerLast ping (in ms)
Voice Connection States
StateDescription
DISCONNECTEDTCP disconnected
AWAITING_ENDPOINTWaiting for voice endpoint
AUTHENTICATINGTCP authenticating
CONNECTINGTCP connecting
CONNECTEDTCP connected
VOICE_DISCONNECTEDTCP connected, Voice disconnected
VOICE_CONNECTINGTCP connected, Voice connecting
VOICE_CONNECTEDTCP connected, Voice connected
NO_ROUTENo route to host
ICE_CHECKINGWebRTC ICE checking
{
  "cmd": "DISPATCH",
  "evt": "VOICE_CONNECTION_STATUS",
  "data": {
    "state": "VOICE_CONNECTED",
    "hostname": "some-server.discord.gg",
    "pings": [20, 13.37],
    "average_ping": 13.37,
    "last_ping": 20
  }
}
Sent when a user in a subscribed voice channel starts or stops speaking. Requires subscribing with a channel_id argument.
{
  "cmd": "DISPATCH",
  "data": { "user_id": "190320984123768832" },
  "evt": "SPEAKING_STOP"
}
Dispatched for message events in subscribed text channels. Deletions only include the message ID. Requires subscribing with a channel_id argument.
{
  "cmd": "DISPATCH",
  "data": {
    "channel_id": "199737254929760256",
    "message": {
      "id": "199743874640379904",
      "content": "test",
      "timestamp": "2016-07-05T04:30:50.776Z",
      "author": {
        "id": "190320984123768832",
        "username": "test user 2",
        "discriminator": "7479",
        "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
        "bot": false
      }
    }
  },
  "evt": "MESSAGE_CREATE"
}
Sent when the client receives a notification. Requires the rpc.notifications.read OAuth2 scope. No subscription arguments needed.
FieldTypeDescription
channel_idstringID of channel where notification occurred
messageobjectMessage that generated this notification
icon_urlstringIcon URL of the notification
titlestringTitle of the notification
bodystringBody of the notification
Rich Presence activity events.
  • ACTIVITY_JOIN — sent when the user clicks a join invite. Contains secret (the join_secret from the activity).
  • ACTIVITY_SPECTATE — sent when the user clicks a spectate invite. Contains secret (the spectate_secret from the activity).
  • ACTIVITY_JOIN_REQUEST — sent when the user receives an Ask to Join request. Contains a partial user object.
{
  "cmd": "DISPATCH",
  "data": {
    "user": {
      "id": "53908232506183680",
      "username": "Mason",
      "discriminator": "1337",
      "avatar": "a_bab14f271d565501444b2ca3be944b25"
    }
  },
  "evt": "ACTIVITY_JOIN_REQUEST"
}