NewSchokr 13 is here. A whole new UI, seven locations, snapshots and more. Read more →

How to send embeds with discord.js and discord.py

Build rich Discord embeds with EmbedBuilder in discord.js v14 or discord.Embed in discord.py, plus the field and character limits to stay under.

Updated · 1 min read

Embeds are the boxed, colored message cards bots use for info, help pages and logs. In discord.js v14 you build them with EmbedBuilder; in discord.py you use discord.Embed. The bot needs the Embed Links permission in the channel, or the embed won't show.

discord.js (v14)

const { EmbedBuilder } = require('discord.js');

const embed = new EmbedBuilder()
  .setColor(0x5865f2)
  .setTitle('Server info')
  .setURL('https://discord.js.org')
  .setAuthor({ name: interaction.user.username, iconURL: interaction.user.displayAvatarURL() })
  .setDescription('Here is some information about this server.')
  .setThumbnail(interaction.guild.iconURL())
  .addFields(
    { name: 'Members', value: String(interaction.guild.memberCount), inline: true },
    { name: 'Created', value: `<t:${Math.floor(interaction.guild.createdTimestamp / 1000)}:R>`, inline: true },
  )
  .setFooter({ text: 'Requested via /serverinfo' })
  .setTimestamp();

await interaction.reply({ embeds: [embed] });

Notes:

  • value must be a string, so wrap numbers with String().
  • setImage(url) adds a large image at the bottom; setThumbnail(url) adds a small one top-right.
  • setFooter and setAuthor take an object in v14, not separate arguments.
  • The <t:...:R> syntax is a Discord timestamp that shows relative time in each user's own time zone.

discord.py

import discord

embed = discord.Embed(
    title="Server info",
    description="Here is some information about this server.",
    color=discord.Color.blurple(),
    timestamp=discord.utils.utcnow(),
)
embed.set_author(name=interaction.user.name, icon_url=interaction.user.display_avatar.url)
if interaction.guild.icon:
    embed.set_thumbnail(url=interaction.guild.icon.url)
embed.add_field(name="Members", value=str(interaction.guild.member_count), inline=True)
embed.add_field(name="Created", value=discord.utils.format_dt(interaction.guild.created_at, "R"), inline=True)
embed.set_footer(text="Requested via /serverinfo")

await interaction.response.send_message(embed=embed)

With prefix commands use await ctx.send(embed=embed). To send several, pass embeds=[a, b].

Embed limits

Discord rejects embeds that exceed these limits:

PartLimit
Title256 characters
Description4,096 characters
Fields25 per embed
Field name256 characters
Field value1,024 characters
Footer text2,048 characters
Author name256 characters
All text combined6,000 characters per message
Embeds10 per message

If you display user-generated or long text, truncate it before adding it. For long lists, split them across pages (see buttons and select menus for page buttons).

Images from your bot's files

To use a local image file in an embed, attach it and reference it with attachment://:

const { AttachmentBuilder } = require('discord.js');
const file = new AttachmentBuilder('./assets/banner.png');
embed.setImage('attachment://banner.png');
await interaction.reply({ embeds: [embed], files: [file] });
file = discord.File("assets/banner.png", filename="banner.png")
embed.set_image(url="attachment://banner.png")
await interaction.response.send_message(embed=embed, file=file)

Embed doesn't show?

  • The bot lacks Embed Links in that channel.
  • The user has link previews turned off in their Discord settings, which hides embeds for them.
  • A field value is empty. Every field needs a non-empty name and value.
  • An image URL isn't a direct, publicly reachable image link.