Fetching Discord Avatars with Next.js & Discord API

Fetching Discord Avatars with Next.js & Discord API

Discord's unique avatars offer a personalized touch to user profiles. Here, we'll explore how you can integrate this feature into your Next.js application using the Discord API.

📚 Prerequisites

  • Familiarity with Next.js
  • Access to Discord Developer Portal
  • Knowledge of environment variables in Next.js

🚀 Setup

Before we proceed, ensure you've setup the following environment variables:

  • USER_ID: Your Discord user ID.
  • BOT_TOKEN: Your bot token from the Discord Developer Portal.

🛠 Building the API Route

First, let's lay the foundation with a new API route. In your Next.js app, navigate to your app/api folder, and create a new folder named avatar and add route.ts file .

Setting Up Your API Route

Start by importing necessary functions:

app/api/avatar/route.ts
import { NextResponse } from "next/server";
 
export async function GET() {
 
}

Defining the Discord User

Next, we'll define the Discord user object. This will be used to fetch the user's avatar.

app/api/avatar/route.ts
interface DiscordUser {
  id: string;
  username: string;
  discriminator: number;
  avatar: string;
}

Crafting the GET function

First we'll destructure the USER_ID and BOT_TOKEN environment variables.

app/api/avatar/route.ts
  export async function GET() {
  const { USER_ID, BOT_TOKEN } = process.env;
 
}

Fetching User Data from Discord API with fetch.

app/api/avatar/route.ts
  const response = await fetch(`https://discord.com/api/v9/users/${USER_ID}`, {
    headers: {
      Authorization: `Bot ${BOT_TOKEN}`,
    },
  });
 

Good applications are always prepared for anomalies. We ensure to catch any potential errors in our request and relay an appropriate message back.

app/api/avatar/route.ts
 const response = await fetch(`https://discord.com/api/v9/users/${USER_ID}`, {
    headers: {
      Authorization: `Bot ${BOT_TOKEN}`,
    },
  });
 if (!response.ok) { //Error handling
    return NextResponse.json({
      status: response.status,
      error: "Failed to fetch Discord user data",
    });
  }

Finally, we'll return the user data as JSON.

app/api/avatar/route.ts
const userData: DiscordUser = await response.json();
{ //userData object
id: '193487726836711426',
username: 'soultel',
avatar: 'e2b68febd45f2544750ca5d15e30a3cb',
discriminator: '0',
}

Extracting Avatar URL

app/api/avatar/route.ts
const avatar_url = userData.avatar
  ? `https://cdn.discordapp.com/avatars/${userData.id}/${userData.avatar}.png?size=256`
  : `https://cdn.discordapp.com/embed/avatars/${userData.discriminator % 5}.png`;

Now we have the avatar URL in avatar_url constant to fecth. After fetching the avatar, we will convert the image into a buffer and send it back, along with the appropriate headers.

app/api/avatar/route.ts
const avatarResponse = await fetch(avatar_url);
const avatarBuffer = await avatarResponse.arrayBuffer();
return new NextResponse(avatarBuffer, {
  headers: {
    "Content-Type": "image/png",
    "Cache-Control": "public, max-age=86400",
  },
});

🎉 Conclusion

We've successfully integrated Discord avatars into our Next.js application. You can now use this API route to fetch avatars for any user on Discord.

Here is an example of how you can use this API route in your Next.js app with next/image.
app/page.tsx
import Image from "next/image";
 
export default function Home() {
  return (
      <Image
        src="/api/avatar"
        width={256}
        height={256}
        alt="Discord Avatar"
      />
  );
}
 

Here is the full code of the API route

app/api/avatar/route.ts
import { NextResponse } from "next/server";
 
interface DiscordUser {
  id: string;
  username: string;
  discriminator: number;
  avatar: string;
}
 
export async function GET() {
  const { USER_ID, BOT_TOKEN } = process.env;
 
  const response = await fetch(`https://discord.com/api/v9/users/${USER_ID}`, {
    headers: {
      Authorization: `Bot ${BOT_TOKEN}`,
    },
  });
  if (!response.ok) {
    return NextResponse.json({
      status: response.status,
      error: "Failed to fetch Discord user data",
    });
  }
 
  const userData: DiscordUser = await response.json();
  const avatar_url = userData.avatar
    ? `https://cdn.discordapp.com/avatars/${userData.id}/${userData.avatar}.png?size=256`
    : `https://cdn.discordapp.com/embed/avatars/${
        userData.discriminator % 5
      }.png`;
 
  const avatarResponse = await fetch(avatar_url);
 
  if (!avatarResponse.ok) {
    return NextResponse.json({
      status: avatarResponse.status,
      error: "Failed to fetch Discord avatar",
    });
  }
 
  const avatarBuffer = await avatarResponse.arrayBuffer();
  
  return new NextResponse(avatarBuffer, {
    headers: {
      "Content-Type": "image/png",
      "Cache-Control": "public, max-age=86400",
    },
  });
}