← Blog
·12 min read

Building a Discord Bot That Shows YouTube Channel Banners

Step by step guide to building a Discord bot with discord.js that displays YouTube channel banners, avatars, and subscriber counts using the banner.yt API.

DiscordBotAPIJavaScriptTutorial
Blog Post Example Banner

Discord Bot for YouTube Channel Banners

This tutorial walks through building a Discord bot that lets users run a command like /banner mrbeast and get back the channel banner, avatar, and stats as a rich embed.

What you need

  • Node.js 18 or newer
  • A Discord bot token (from discord.com/developers)
  • discord.js v14
  • The banner.yt API (no key required)

Project setup

mkdir yt-banner-bot && cd yt-banner-bot
npm init -y
npm install discord.js

index.js

const { Client, GatewayIntentBits, EmbedBuilder, SlashCommandBuilder } = require('discord.js');
const { REST, Routes } = require('discord.js');

const TOKEN = process.env.DISCORD_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.on('ready', () => {
  console.log('Bot ready as', client.user.tag);
});

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'banner') return;

  const query = interaction.options.getString('channel');
  await interaction.deferReply();

  try {
    // Search for the channel first
    const searchRes = await fetch(
      `https://banner.yt/api/search?q=${encodeURIComponent(query)}`
    );
    const { results } = await searchRes.json();

    if (!results || results.length === 0) {
      return interaction.editReply('Could not find that channel.');
    }

    const topResult = results[0];
    const { channelId, title } = topResult;

    // Get full channel data
    const channelRes = await fetch(`https://banner.yt/api/channel/${channelId}`);
    const channel = await channelRes.json();

    const bannerUrl = `https://banner.yt/api/banner/${channelId}?format=jpeg`;
    const avatarUrl = `https://banner.yt/api/banner/${channelId}?type=avatar&format=jpeg`;

    const embed = new EmbedBuilder()
      .setTitle(channel.title || title)
      .setURL(`https://www.youtube.com/channel/${channelId}`)
      .setDescription(channel.description?.slice(0, 100) || '')
      .setImage(bannerUrl)
      .setThumbnail(avatarUrl)
      .addFields(
        { name: 'Subscribers', value: formatNumber(channel.subscriberCount), inline: true },
        { name: 'Total Views', value: formatNumber(channel.viewCount), inline: true },
        { name: 'Channel ID', value: channelId, inline: false },
      )
      .setColor(0xFF0000)
      .setFooter({ text: 'banner.yt' });

    await interaction.editReply({ embeds: [embed] });
  } catch (err) {
    await interaction.editReply('Something went wrong, try again.');
  }
});

function formatNumber(n) {
  if (!n) return 'N/A';
  const num = parseInt(n, 10);
  if (num >= 1_000_000) return (num / 1_000_000).toFixed(1) + 'M';
  if (num >= 1_000) return (num / 1_000).toFixed(1) + 'K';
  return num.toString();
}

// Register slash command
const commands = [
  new SlashCommandBuilder()
    .setName('banner')
    .setDescription('Get a YouTube channel banner')
    .addStringOption(opt =>
      opt.setName('channel').setDescription('Channel name or ID').setRequired(true)
    ),
].map(c => c.toJSON());

const rest = new REST().setToken(TOKEN);
rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands })
  .then(() => console.log('Commands registered'))
  .catch(console.error);

client.login(TOKEN);

Running the bot

DISCORD_TOKEN=your_token CLIENT_ID=your_client_id node index.js

Now any server member can type /banner MrBeast and the bot will reply with the banner image, avatar, subscriber count, and view count in a clean embed.

Add more commands

You can extend this to add a /avatar command, a /stats command for just the numbers, or even a /compare command that shows two channels side by side.