Overview
Buttons are interactive components that users can click in Discord messages. Each button can trigger an interaction event or open a URL.
Create a blurple primary button.
The custom ID used to identify this button (max 100 characters)
The text displayed on the button (max 80 characters)
static Button primary(@Nonnull String customId, @Nonnull String label)
Create a gray secondary button.
The custom ID used to identify this button
The text displayed on the button
static Button secondary(@Nonnull String customId, @Nonnull String label)
Create a green success button.
The custom ID used to identify this button
The text displayed on the button
static Button success(@Nonnull String customId, @Nonnull String label)
Create a red danger button.
The custom ID used to identify this button
The text displayed on the button
static Button danger(@Nonnull String customId, @Nonnull String label)
Create a button that opens a URL when clicked.
The URL to open (max 512 characters)
The text displayed on the button
static Button link(@Nonnull String url, @Nonnull String label)
Link buttons do not send interaction events - they simply open the URL in the user’s browser.
SlashBotExample.java:248-256
// prompt the user with a button menu
event.reply("This will delete " + amount + " messages.\nAre you sure?")
.addComponents(ActionRow.of(
// this means "<style>(<id>, <label>)"
// you can encode anything you want in the id (up to 100 characters)
Button.secondary(userId + ":delete", "Nevermind!"),
Button.danger(
// the first parameter is the component id we use in onButtonInteraction above
userId + ":prune:" + amount, "Yes!")))
.queue();
withEmoji()
Add an emoji to the button.
The emoji to display on the button
default Button withEmoji(@Nullable Emoji emoji) {
return new ButtonImpl(
getCustomId(), getUniqueId(), getLabel(), getStyle(), getUrl(), getSku(), isDisabled(), emoji)
.checkValid();
}
withLabel()
Change the button’s label.
The new label text (max 80 characters)
default Button withLabel(@Nonnull String label) {
return new ButtonImpl(
getCustomId(), getUniqueId(), label, getStyle(), getUrl(), getSku(), isDisabled(), getEmoji())
.checkValid();
}
asDisabled() / asEnabled()
Disable or enable the button.
default Button asDisabled() {
return (Button) ActionComponent.super.asDisabled();
}
default Button asEnabled() {
return (Button) ActionComponent.super.asEnabled();
}
ComponentsV2Example.java:228-230
ActionRow.of(
Button.secondary("previous", "⬅ Social Space"),
Button.success("back", "Back").withEmoji(backEmoji),
Button.secondary("next", "Prairie Village ➡"))
Listen for button click events.
SlashBotExample.java:133-163
@Override
public void onButtonInteraction(ButtonInteractionEvent event) {
// this is the custom id we specified in our button
String[] id = event.getComponentId().split(":");
String authorId = id[0];
String type = id[1];
// Check that the button is for the user that clicked it, otherwise just ignore the event (let interaction fail)
if (!authorId.equals(event.getUser().getId())) {
return;
}
// acknowledge the button was clicked, otherwise the interaction will fail
event.deferEdit().queue();
MessageChannel channel = event.getChannel();
switch (type) {
case "prune" -> {
int amount = Integer.parseInt(id[2]);
event.getChannel()
.getIterableHistory()
.skipTo(event.getMessageIdLong())
.takeAsync(amount)
.thenAccept(channel::purgeMessages);
// delete the prompt message with our buttons
event.getHook().deleteOriginal().queue();
}
case "delete" -> {
event.getHook().deleteOriginal().queue();
}
}
}
getLabel()
Get the button’s label text.
@Nonnull
String getLabel()
getStyle()
Get the button’s style (PRIMARY, SECONDARY, SUCCESS, DANGER, LINK, PREMIUM).
@Nonnull
ButtonStyle getStyle()
getCustomId()
Get the custom ID for this button (null for link buttons).
@Nullable
String getCustomId()
getUrl()
Get the URL for link buttons.
@Nullable
String getUrl()
getEmoji()
Get the emoji attached to this button.
@Nullable
EmojiUnion getEmoji()
isDisabled()
Check if the button is disabled.
Action Rows
Buttons must be placed in action rows. Each action row can contain up to 5 buttons.
import net.dv8tion.jda.api.components.actionrow.ActionRow;
event.reply("Choose an option")
.addComponents(
ActionRow.of(
Button.primary("option1", "Option 1"),
Button.primary("option2", "Option 2"),
Button.primary("option3", "Option 3")
)
)
.queue();
Constants
Button.LABEL_MAX_LENGTH - 80 characters maximum for button labels
Button.ID_MAX_LENGTH - 100 characters maximum for custom IDs
Button.URL_MAX_LENGTH - 512 characters maximum for URLs
Best Practices
Use meaningful custom IDs that help you identify the button’s purpose and context. You can encode multiple pieces of information separated by colons or other delimiters.
Always acknowledge button interactions with deferEdit(), deferReply(), or an immediate reply/edit, otherwise the interaction will fail after 3 seconds.
Link buttons don’t require custom IDs and don’t trigger interaction events. They’re perfect for documentation links, support pages, or external resources.