iTranslated by AI
A Complete Guide to Discord Bot Development
1. Introduction
Discord Bots can be easily created using SDKs.
The range of expressions possible with Discord Bots is wide, including not only sending text messages but also embeds and voice messages.
In this article, I will introduce what you can express with a Discord Bot and points to keep in mind during operation when creating a new Discord Bot.
The content of this article is created using Go(v1.20) and discordgo(v0.27.1).
Also, since the content is independent for each chapter, please refer to the table of contents as needed.
Target Audience
- People who don't quite know what can be done with a Discord Bot
- People who want to create a Discord Bot
- People who want to know about operating a Discord Bot
2. Types of Message Expressions in Discord Bot
2.1. Text Message
- This is the basic message format.
- You can send text up to 2000 characters.

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
_, err = dg.ChannelMessageSend(channelID, "Hello, Test Channel!")
2.2. Files
You can send and share files such as images, videos, and documents.

Basic formats are supported, and as an example, the following can be attached:
Images: .jpg, .jpeg, .png, .gif, .webp
Videos: .mp4, .mov
Audio: .mp3, .wav
Text: .txt, .md, .log
Documents: .pdf, .doc, .docx, .ppt, .pptx, .xls, .xlsx
Compressed files: .zip, .rar, .tar.gz
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
resp, err := http.Get("")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Send a file as a message
message := &discordgo.MessageSend{
Content: "Image:",
Files: []*discordgo.File{
{
Name: "sugar.png",
Reader: resp.Body,
},
},
}
_, err = dg.ChannelMessageSendComplex(channelID, message)
2.3. Reactions
-
You can add reactions to messages using emojis.
-
There are two types of emojis that can be used as reactions.
-
Unicode Emoji

Custom Emoji

Implementation Example
// Unicode Emoji
err = dg.MessageReactionAdd(channelID, message.ID, "😀")
// Custom Emoji: needs to be encoded in name:id format.
err = dg.MessageReactionAdd(channelID, message.ID, "emoji_name:emoji_id")
- emoji_id is the
XXXpart obtained from the sticker link.https://cdn.discordapp.com/emojis/?XXX.webp

2.4. Replies
- You can reply to specific messages.

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
m, _ := dg.ChannelMessageSend(channelID, "Hello, Test Channel!")
message := &discordgo.MessageSend{
Content: "This is a reply!",
// Specify the relevant message ID and send the content
Reference: &discordgo.MessageReference{MessageID: m.ID},
}
_, err = dg.ChannelMessageSendComplex(channelID, message)
2.5. Threads
-
You can create message threads organized by topic.
-
Thread names: 1–100 characters.
-
The duration until the thread is hidden can be adjusted.

Implementation Example
thread, err := s.MessageThreadStartComplex(m.ChannelID, m.ID, &discordgo.ThreadStart{
// see: https://discord.com/developers/docs/resources/channel#start-thread-from-message
Name: "Pong game with " + m.Author.Username,
AutoArchiveDuration: 60,
Invitable: false,
RateLimitPerUser: 10,
})
if err != nil {
log.Println("Error starting thread:", err)
return
}
_, err = s.ChannelMessageSend(thread.ID, "pong")
2.6. Context Menu
A menu that provides additional actions related to a message.

Implementation Example
func registerContextMenu(s *discordgo.Session, guildID string) {
// Define the context menu
// see: https://discord.com/developers/docs/interactions/application-commands#create-global-application-command
cmd := &discordgo.ApplicationCommand{
Name: "share-with-me",
Type: discordgo.MessageApplicationCommand,
}
_, err := s.ApplicationCommandCreate(s.State.User.ID, guildID, cmd)
if err != nil {
log.Println("Failed to create context menu:", err)
}
}
2.7. Embed Messages
This is a rich message format.

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
embed := &discordgo.MessageEmbed{
Title: "Embed Title",
Description: "This is an embed message",
Color: 0x00ff00, // Green
}
_, err = dg.ChannelMessageSendEmbed(channelID, embed)
- The embed target can be customized.

2.8. TTS (Text-to-Speech) Messages
A message format that converts text to speech and reads it aloud.
Caution: Volume
- If the user has disabled TTS, the message will appear as regular text.
- Fine settings such as pitch and speed of the TTS voice cannot be customized.
- TTS messages are only played in text channels.
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
_, err = dg.ChannelMessageSendTTS(channelID, "Hello in Text-to-Speech!")
2.9. Components (Buttons and Select Menus)
UI components that can be used within messages.
1. ButtonComponent
- Interactive button components displayed within messages.
- When a user clicks them, an interaction can be sent to the app.
- They must be sent within an action row.
- An action row can contain up to 5 buttons and cannot include a select menu component at the same time.

Refer to the following for button types.
Implementation Example
&discordgo.MessageComponent{
Type: discordgo.ButtonComponent,
Label: "Click Me!",
Style: discordgo.PrimaryButton, // Example: Primary button
CustomID: "button_click",
}
2. SelectMenuComponent
- Interactive components where users select options from a dropdown list within a message.
- Supports single-select and multi-select.
- Must be sent within an action row, and one action row can contain only one select menu. Select menus and buttons cannot be included at the same time.

Implementation Example
&discordgo.MessageComponent{
&discordgo.SelectMenu{
CustomID: "select_option",
Options: []discordgo.SelectMenuOption{
{
Label: "Option 1",
Value: "opt1",
},
{
Label: "Option 2",
Value: "opt2",
},
},
},
}
3. TextInputComponent
- Text input is an interactive component displayed in a modal.
- Suitable for collecting short or long-form text.

*This component is only available in Interactions.
Implementation Example
discordgo.TextInput{
CustomID: "text_input",
Placeholder: "Enter some text here",
Style: discordgo.TextInputParagraph,
}
- It is a feature that allows you to respond to user actions using components such as buttons, select menus, and slash commands.
Types of Interactions:
-
Slash Commands:
- A feature to launch commands using
/. - You can create custom commands to trigger specific actions or responses.
- They can be registered for global use or only in specific servers.
- A feature to launch commands using
-
Message Components:
- You can embed the components mentioned earlier (such as TextInput).
-
Context Menus:
- Right-click menus for adding custom actions to users or messages.
- They have a registration and processing flow similar to slash commands.
When performing heavy processing, it is necessary to process asynchronously while keeping the time limit in mind.
The article below achieves asynchronous processing while returning a response to the Discord Bot by setting up an endpoint that accepts requests and redirects them to a PubSub queue.
2.10. Schedule
This is a scheduling feature that allows you to send messages at a specific time or date.
- You can register up to 100 events.

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
params := &discordgo.GuildScheduledEventParams{
Name: "Event Name",
Description: "Event Description",
ScheduledStartTime: &startTime,
ScheduledEndTime: &endTime,
PrivacyLevel: discordgo.GuildScheduledEventPrivacyLevelGuildOnly,
EntityType: discordgo.GuildScheduledEventEntityTypeExternal,
EntityMetadata: &discordgo.GuildScheduledEventEntityMetadata{Location: "Location Information"},
}
// Create a scheduled event
_, err = dg.GuildScheduledEventCreate(guildID, params)
2.11. Audio Messages in Voice Channels
You can achieve voice communication with users.
Caution: Volume
| Feature | Implementation Example | Description |
|---|---|---|
| Joining/Leaving Voice Channels |
dg.ChannelVoiceJoin(...) / v.Disconnect()
|
Basic methods for the Bot to join or leave a voice channel. |
| Receiving Audio | v.OpusRecv |
Method for the Bot to receive audio from other users. Specifically, it is possible to obtain PCM data. |
| Sending Audio | v.OpusSend |
Method for the Bot to send audio to other users. Specifically, it receives audio data in Opus format. |
| User Mute Control | dg.GuildMemberMute(...) |
Method to mute or unmute a specific user. |
| User Volume Adjustment | - (No direct method in Discord API) | Feature to adjust a user's volume. Specific implementation requires manipulating the audio data. |
| Playing Audio Files | Custom implementation required | Read an audio file, convert it to Opus format, and use v.OpusSend to send it to the voice channel. |
| Interactive Command Processing with Users | Custom implementation required | Receive commands from users in a text channel and implement interactive processing, such as changing the behavior of the Voice Bot accordingly. |
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
// Accepts the ID of the guild and channel the bot joins, as well as options like mute or speaker status as arguments.
v, err := dg.ChannelVoiceJoin(guildID, channelID, true, false)
- Sending sound effects in a voice channel
- Load audio files in
dcaformat
- Load audio files in
func playSound(s *discordgo.Session, guildID, channelID string) (err error) {
vc, err := s.ChannelVoiceJoin(guildID, channelID, false, true)
if err != nil {
return err
}
defer vc.Disconnect()
time.Sleep(250 * time.Millisecond)
vc.Speaking(true)
for _, buff := range buffer {
vc.OpusSend <- buff
}
vc.Speaking(false)
time.Sleep(250 * time.Millisecond)
return nil
}
- Recording
- Sound effects
3. Discord Bot Operation
3.1. Development Languages
The main languages for developing Bots and the characteristics of their respective SDKs are as follows:
There are many languages available for developing Discord Bots. Below is a summary of the main languages, their SDK characteristics, and information sources.
| Language | SDK Characteristics | OSS |
|---|---|---|
| Python | Possible to develop advanced Bots by combining with rich libraries. Primarily supports asynchronous processing. | discord.py, hikari |
| JavaScript | Library for Bots running on Node.js. Supports asynchronous processing, enabling efficient Bot development. | discord.js, Eris |
| Java | Enables Bot development leveraging type safety. Suitable for developing and operating large-scale Bots. | JDA, Discord4J |
| C# | Enables Bot development based on the .NET framework. Supports asynchronous processing and event-driven architecture. | Discord.Net, DSharpPlus |
| Go | Enables development of high-performance Bots excelling in concurrency by leveraging Go's characteristics. | discordgo |
| Clojure | Bot development in a functional language running on the JVM. | discljord |
| C++ | Bot development focused on performance. | D++ |
| Lua | Bot development in a lightweight scripting language. | Discordia |
| PHP | Bot development emphasizing integration with web applications. | DiscordPHP |
| Rust | Safe and high-performance Bot development. | Serenity |
| Ruby | Bot development leveraging object-oriented features. | discordrb |
3.2. Interactions
There are many libraries and tools to support Interactions.
They provide helpers for security and authentication checks, which are essential when receiving Interactions via Webhooks, as well as data model types.
Some of the representative ones are introduced below.
| Language | Characteristics | Source |
|---|---|---|
| C# | Support for Interactions via outgoing webhooks. | Discord.Net.Rest |
| Dart | Includes Slash commands support and Commands framework; works cross-platform and allows control over all outgoing HTTP requests and WebSocket messages. | nyxx |
| Go | Fast API wrapper with minimal caching. | Tempest |
| Javascript | Provides types and helper functions useful for implementing Interactions webhooks. | discord-interactions-js |
| Python | Interactions support library for Python. | discord-interactions-python |
| PHP | Provides types and helper functions useful for implementing Interactions webhooks. | discord-interactions-php |
3.3. API Types
Simple type definitions for the Discord API.
| Name | Language |
|---|---|
| dasgo | Go |
| discord-api-types | JavaScript |
3.4. Tools Supporting Discord Bot Development
Game SDK Tools
The network layer of the Discord Game SDK is similar to other game platforms (e.g., Valve's Steamworks SDK).
By using the following OSS, you can simplify development across multiple platforms by providing a unified interface for shared features.
| Tool Name | Details | Supported Platforms |
|---|---|---|
| HouraiNetworking | Library for Unity3D | Unity3D |
Dispatch Tools
Tools used when publishing games on Discord using Discord's Dispatch tools.
| Tool Name | Details |
|---|---|
| JohnyTheCarrot's Dispatch CLI | Webhook support when pushing game updates |
Permission Calculators
Discord permissions are complex, but they can be easily calculated using the tools below.
| Tool Name | Details |
|---|---|
| FiniteReality's Permissions Calculator | Permission calculation tool |
| abalabahaha's Permissions Calculator | Permission calculation tool |
Intent Calculators
Can be used to calculate intents. (Intents are used to subscribe a Bot to specific sets of events.)
| Tool Name | Details |
|---|---|
| ziad87's Intent Calculator | Intent calculation tool |
| Larko's Intent Calculator | Intent calculation tool |
Embed Visualizers
Tools useful for visualizing Embeds.
| Tool Name | Details |
|---|---|
| Autocode Embed Builder | Embed visualizer |
| JohnyTheCarrot's Embed Previewer | Browser extension for testing Embed display within Discord |
3.5. Hosting Options (Free Tiers)
There are various options for hosting your Bot.
Representative managed services that can be run 24/7 on a free tier are as follows:
| Service Name | Cost (Month) | RAM | CPU | Storage | Network Transfer | Notes |
|---|---|---|---|---|---|---|
| Render | $0 (Limits apply) | 512 MB | 0.1 vCPU | - | - | Limit Details |
| fly.io | Free plan available | 256 MB (up to 3 VMs) | Shared CPU (up to 3 VMs) | 3 GB (Total) | 160 GB | 3 VMs (Total of V2 apps, V1 apps, Machines) |
| replit | Free plan available | 0.5 GiB | 0.5 vCPUs | 10 GiB | 10 GiB (Development) | Unlimited Public Repls |
| Railway | First $5 free | $10/GB/month | $20/vCPU/month | $0.25/GB/month (Optional) | $0.10/GB | Transfer rates from August 1, 2023 |
Besides the above, hosting choices vary depending on the Bot's features, such as only operating via Interactions or not accepting user input.
If 24/7 operation is not necessary and using only HTTP Interactions is sufficient, consider hosting via FaaS such as Lambda or Cloudflare Workers.
3.6. When Making it Publicly Available
When releasing a Discord Bot to the public, attention is required for various aspects such as security, user convenience, and API limitations.
Basic Information
- If the Bot is to be made public, it must be configured in the Discord Developer Portal.
- Public settings can be configured in the "OAuth2" tab of the Discord Developer Portal.
- If you are adding the Bot to more than 100 servers, a separate application is required. (Identity verification will be performed on the Dev Portal once it is added to more than 75 servers.)
Permissions and Feature Restrictions
To prevent misuse, it is basic practice to grant only the minimum necessary permissions to the bot.
Bot permission management uses a whitelist-style authorization system. (Actions cannot be executed unless permissions are explicitly granted to the bot.)

Also, by setting command permissions on the server side, it is possible to restrict the execution of command (/hoge) Interactions for each user.
About API Limits
The Discord API has certain limits. Exceeding these may cause the Bot to temporarily stop working.
1. Rate Limit Types and Details
| Type | Description | Limit |
|---|---|---|
| Per-route | Limits for individual endpoints. Depends on HTTP method and endpoint type. Refer to the X-RateLimit-Bucket header. |
Value shown in the X-RateLimit-Limit header |
| Global | Limits for requests made by the bot or user as a whole. | 50 requests per second |
| Emoji-specific | Endpoints related to emojis have different limits than normal. | No specific limit is provided |
| Invalid Request | Limits for invalid HTTP requests. Primarily related to 401, 403, and 429 statuses. | 10,000 requests per 10 minutes |
2. Main Rate Limit Related Headers
| Header Name | Description |
|---|---|
X-RateLimit-Limit |
Request limit for that endpoint |
X-RateLimit-Remaining |
Remaining number of requests |
X-RateLimit-Reset |
Epoch time when the rate limit resets (seconds since 00:00:00 UTC on January 1, 1970) |
X-RateLimit-Reset-After |
Time until the rate limit resets (seconds) |
X-RateLimit-Bucket |
Unique identifier for the rate limit |
X-RateLimit-Global |
Flag returned only during a 429 response, indicating a global rate limit hit |
X-RateLimit-Scope |
Returned only during a 429 response, indicating the type of rate limit: user, global, or resource |
The API response is returned as HTTP 429. The response includes a Retry-After header or retry_after field, indicating the wait time before retrying.
Important Note: To avoid hitting rate limits, applications should properly parse response headers and operate according to the limits. In particular, properly handling error responses such as 401 or 403 can reduce the risk of hitting the invalid request limit.
4. Introduction of Publicly Available Bots
- You can view a ranking of publicly available Discord Bots.
- VOICEVOX Text-to-Speech Bot
- (Created by the author) Bot that notifies of streaming for a Vtuber group
Tweet
5. References
Discussion