A Discord permission integer records a set of flags. It is useful for understanding a role or building a bot invite, but it does not by itself tell you what a member can do in every channel. This guide explains the math and the checks to make when a bot reports missing permissions. For individual values, use the permission flag reference.

Combine flags with OR, inspect them with AND

View Channel is 1024 and Send Messages is 2048. Combining them gives 3072. Use BigInt for bitwise operations in JavaScript: ordinary Number bitwise operators use signed 32-bit integers, which cannot represent the full set.

const viewChannel = 1024n;
const sendMessages = 2048n;
const embedLinks = 16384n;
const permissions = viewChannel | sendMessages;
console.log(permissions.toString()); // "3072"
console.log((permissions & sendMessages) === sendMessages); // true
console.log((permissions & embedLinks) === embedLinks); // false

The parentheses matter. An expression such as permissions & flag === flag compares before performing the AND. Also avoid adding the same flag twice; OR remains correct when a flag is already present.

Decode a real number

A role bitfield of 84992 contains View Channel (1024), Send Messages (2048), Embed Links (16384), and Read Message History (65536). Paste it into the Discord Permissions Calculator to see the flags. This is an example, not a required permission set for every bot.

Moderate Members, the timeout permission, is 1099511627776 at bit 40. Request to Speak is 4294967296 at bit 32. Similar-looking large values represent different capabilities; do not copy an unexplained aggregate from another bot.

Keep API permission values as decimal strings

Discord serializes permission values as strings in current API versions. Convert to BigInt for local arithmetic, and back to a string for JSON. JSON serialization does not directly support BigInt values.

const role = { permissions: "84992" };
const value = BigInt(role.permissions);
const next = value | 32768n; // Add Attach Files.
const json = JSON.stringify({ permissions: next.toString() });
console.log(json); // {"permissions":"117760"}

Build an invite without confusing scopes and permissions

In the Developer Portal, choose the installation context and scopes your app needs. A bot installation uses the bot scope; applications.commands concerns application commands. The permissions query parameter requests bot permissions during installation. The Use Application Commands role flag controls a member's access to commands; it is not a substitute for the OAuth2 scope.

https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot%20applications.commands&permissions=3072

Use the calculator to select only the flags needed for your bot's actions. Installation permissions can be adjusted later through server roles and channel overwrites.

Why a correct bitfield can still produce Missing Permissions

  1. Check the member's combined server roles, including @everyone.
  2. Inspect the channel's @everyone overwrite, then role overwrites and member-specific overwrites.
  3. Check prerequisites such as View Channel. A permission to send a message is not useful in a channel the bot cannot view.
  4. For role editing and moderation, check the bot's highest role against its target. A higher role does not automatically win all channel overwrite conflicts.
  5. For threads, check Send Messages in Threads rather than assuming Send Messages is sufficient.

Administrator (8) bypasses channel overwrites, but role hierarchy still restricts certain moderation and role-management actions. Granting Administrator is not a general fix for a misunderstood overwrite.

Using discord.js

import { PermissionFlagsBits, PermissionsBitField } from 'discord.js';
const requested = new PermissionsBitField([
  PermissionFlagsBits.ViewChannel,
  PermissionFlagsBits.SendMessages,
]);
console.log(requested.bitfield.toString()); // "3072"
// In your command handler, evaluate the bot's permissions in that channel:
// const effective = channel.permissionsFor(guild.members.me);
// effective?.has(PermissionFlagsBits.SendMessages);

The installed library version determines which named flags it exposes. The decimal and bit-position reference helps compare a library value with the API documentation.

Sources