Bot de bienvenida para Discord: mensaje al entrar y rol automático (Python y JavaScript)
Un mensaje que salude a cada persona por su nombre, con su foto, y un rol que se dé solo al entrar: es lo primero que se le pide a un bot propio. Son 60 líneas en Python (discord.py) o en JavaScript (discord.js), y casi todo lo que falla no es el código sino tres ajustes de Discord. Aquí van el código y los tres.
Antes de programar: lo que Discord ya hace solo
Si te basta con un saludo, Discord ya lo trae: en «Ajustes del servidor», en la primera pantalla, eliges el canal de mensajes del sistema y activas el mensaje de bienvenida aleatorio. Y los servidores de comunidad tienen la «Incorporación» (Onboarding), que da roles según lo que cada uno contesta al entrar.
Un bot propio hace lo que eso no hace: tu texto, una tarjeta con la foto y el número de miembro, la mención para que le llegue el aviso, un rol para todo el que entra (o solo cuando acepta las normas) y lo que quieras añadir después, como la despedida.
¿Prefieres no montarlo tú? Hosting de bots de Discord desde 1,50 € al mes, sin permanencia y con devolución íntegra en 72 horas. O crea un bot de Discord gratis, sin tarjeta.
1. Crea el bot y activa «Server Members Intent»
Crea la aplicación y saca el token
En discord.com/developers/applications, «New Application»; en la pestaña «Bot», «Reset Token» y copia el token. Es la contraseña del bot: no lo compartas ni lo subas a GitHub. Si es tu primer bot, la guía de bot en Python o en JavaScript lo cuenta con calma.
Activa «Server Members Intent»
En la misma pestaña «Bot», en «Privileged Gateway Intents», enciende «Server Members Intent» y guarda. Es lo que más se olvida: sin él, Discord no le dice al bot quién entra y el bot no hace nada, sin ningún error. Y si el código lo pide y aquí está apagado, el bot ni arranca (discord.py dice PrivilegedIntentsRequired; discord.js, «Used disallowed intents»).
Invítalo con los permisos justos
En «OAuth2» → «URL Generator», marca «bot» y «applications.commands», y de permisos «View Channels», «Send Messages», «Embed Links» y «Manage Roles». Abre el enlace que sale y añádelo a tu servidor.
2. Sube el rol del bot por encima del rol que da
Un bot solo puede dar roles que estén por debajo de su propio rol en la lista. Al entrar, Discord le crea un rol con su nombre y lo pone abajo del todo, así que el primer intento falla con «Missing Permissions» (código 50013) aunque le hayas dado «Manage Roles».
En «Ajustes del servidor» → «Roles», arrastra el rol del bot por encima del rol que tiene que dar (por ejemplo, «Miembro») y guarda. Y que ese rol no tenga permisos peligrosos: lo va a recibir cualquiera que entre.
3. Saca los ids del canal y del rol
El bot busca el canal y el rol por su id, no por su nombre: así sigue funcionando aunque los renombres. Para verlos, en «Ajustes de usuario» → «Avanzado», enciende el «Modo desarrollador». Luego, clic derecho en el canal de bienvenida → «Copiar ID del canal», y en «Ajustes del servidor» → «Roles», clic derecho en el rol → «Copiar ID del rol». Los dos van al fichero .env. Si no quieres dar ningún rol, deja ROL_NUEVOS vacío.
4. El código en Python (discord.py)
Tres ficheros en una carpeta. Con Python 3.10 o más nuevo: «pip install -r requirements.txt» y «python app.py». Cuando diga «Conectado como…», ya saluda.
discord.py
python-dotenvDISCORD_TOKEN=pega-aquí-tu-token
CANAL_BIENVENIDA=id-del-canal
ROL_NUEVOS=id-del-rolimport os
import discord
from discord import app_commands
from dotenv import load_dotenv
load_dotenv() # lee el token y los ids del fichero .env
CANAL_ID = int(os.environ["CANAL_BIENVENIDA"])
ROL_ID = int(os.environ.get("ROL_NUEVOS") or 0) # 0 = no dar ningún rol
intents = discord.Intents.default()
intents.members = True # sin esto, Discord no le dice al bot quién entra
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)
def tarjeta(miembro: discord.Member) -> discord.Embed:
embed = discord.Embed(
title=f"¡Te damos la bienvenida a {miembro.guild.name}!",
description=f"Hola, {miembro.mention}. Pásate por las normas y preséntate.",
color=0x5B4AE8,
)
embed.set_thumbnail(url=miembro.display_avatar.url)
embed.set_footer(text=f"Eres el miembro número {miembro.guild.member_count}")
return embed
async def dar_rol(miembro: discord.Member):
rol = miembro.guild.get_role(ROL_ID)
if rol and rol not in miembro.roles:
await miembro.add_roles(rol, reason="Rol de bienvenida")
@client.event
async def on_member_join(miembro: discord.Member):
canal = miembro.guild.get_channel(CANAL_ID)
if canal:
# la mención va fuera del embed: dentro no le llega el aviso
await canal.send(content=miembro.mention, embed=tarjeta(miembro))
if not miembro.pending: # si el servidor pide aceptar las normas, espera
await dar_rol(miembro)
@client.event
async def on_member_update(antes: discord.Member, ahora: discord.Member):
if antes.pending and not ahora.pending: # acaba de aceptar las normas
await dar_rol(ahora)
@tree.command(name="probar-bienvenida", description="Te enseña el mensaje de bienvenida")
@app_commands.default_permissions(manage_guild=True)
@app_commands.guild_only()
async def probar(interaction: discord.Interaction):
await interaction.response.send_message(embed=tarjeta(interaction.user), ephemeral=True)
@client.event
async def on_ready():
await tree.sync() # publica /probar-bienvenida
print(f"Conectado como {client.user}")
client.run(os.environ["DISCORD_TOKEN"])5. O en JavaScript (discord.js)
Lo mismo con Node.js 20 o más nuevo: «npm install» y «node index.js». El .env es el mismo que el de Python.
{
"name": "bot-bienvenida",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"discord.js": "^14.27.0",
"dotenv": "^16.4.0"
}
}require("dotenv").config(); // lee el token y los ids del fichero .env
const {
Client, EmbedBuilder, Events, GatewayIntentBits, InteractionContextType,
MessageFlags, PermissionFlagsBits, SlashCommandBuilder,
} = require("discord.js");
// GuildMembers: sin esto, Discord no le dice al bot quién entra
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] });
function tarjeta(miembro) {
return new EmbedBuilder()
.setColor(0x5b4ae8)
.setTitle(`¡Te damos la bienvenida a ${miembro.guild.name}!`)
.setDescription(`Hola, ${miembro}. Pásate por las normas y preséntate.`)
.setThumbnail(miembro.displayAvatarURL())
.setFooter({ text: `Eres el miembro número ${miembro.guild.memberCount}` });
}
async function darRol(miembro) {
const rol = process.env.ROL_NUEVOS;
if (rol && !miembro.roles.cache.has(rol)) await miembro.roles.add(rol, "Rol de bienvenida");
}
client.on(Events.GuildMemberAdd, async (miembro) => {
const canal = miembro.guild.channels.cache.get(process.env.CANAL_BIENVENIDA);
// la mención va fuera del embed: dentro no le llega el aviso
if (canal) await canal.send({ content: `${miembro}`, embeds: [tarjeta(miembro)] });
if (!miembro.pending) await darRol(miembro); // si el servidor pide aceptar las normas, espera
});
client.on(Events.GuildMemberUpdate, async (antes, ahora) => {
if (antes.pending && !ahora.pending) await darRol(ahora); // acaba de aceptar las normas
});
const probar = new SlashCommandBuilder()
.setName("probar-bienvenida")
.setDescription("Te enseña el mensaje de bienvenida")
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
.setContexts(InteractionContextType.Guild);
client.on(Events.InteractionCreate, async (i) => {
if (!i.isChatInputCommand() || i.commandName !== "probar-bienvenida") return;
await i.reply({ embeds: [tarjeta(i.member)], flags: MessageFlags.Ephemeral });
});
client.once(Events.ClientReady, async (c) => {
await c.application.commands.set([probar.toJSON()]); // publica /probar-bienvenida
console.log(`Conectado como ${c.user.tag}`);
});
client.login(process.env.DISCORD_TOKEN);Si tu servidor pide aceptar las normas
En los servidores con verificación de normas, quien entra queda como «pendiente» hasta que las acepta. Un bot que da el rol nada más entrar se salta esa verificación: con el rol puesto, ya puede escribir sin haber aceptado nada. Por eso el código mira si el miembro está pendiente (pending) y, si lo está, espera a que acepte para darle el rol. En un servidor sin verificación, nadie queda pendiente y el rol llega al momento.
El saludo sale igualmente al entrar. Si prefieres saludar solo a quien acepta, mueve el envío del mensaje a la parte que da el rol.
Pruébalo sin esperar a que entre alguien
El bot trae un comando, /probar-bienvenida, que te enseña la tarjeta tal como la verá quien entre, solo a ti. Solo lo ven quienes pueden gestionar el servidor. La primera vez, Discord puede tardar unos minutos en enseñar el comando.
Para probar el rol hace falta que entre alguien de verdad: un amigo o una segunda cuenta tuya. Si el mensaje sale y el rol no, es la jerarquía del paso 2; si no sale nada, el «Server Members Intent» del paso 1 o el id del canal.
Ideas para ir más allá
Despedida: el evento on_member_remove en discord.py (GuildMemberRemove en discord.js) avisa cuando alguien se va, con el mismo permiso; solo hay que mandar otro mensaje.
Mensaje privado al entrar: miembro.send(), igual en las dos librerías. Mucha gente tiene los mensajes privados cerrados y ahí falla, así que envuélvelo para que el error no corte lo demás (try/except discord.Forbidden, o un .catch()).
Tarjeta con imagen, con el avatar sobre un fondo: se dibuja con Pillow en Python o @napi-rs/canvas en Node.js y se manda como archivo. Gasta algo más de memoria y de procesador que un embed.
Varios servidores: este bot usa un canal y un rol fijos. Para que sirva en más de un servidor, guarda el canal y el rol de cada uno (un fichero JSON basta al principio) con un comando para configurarlo.
6. Déjalo encendido siempre (gratis)
El bot solo saluda mientras su programa está encendido: si lo tienes en tu ordenador y lo apagas, la gente que entre esa noche no tendrá ni mensaje ni rol.
En NapNodes: crea el bot gratis, si es el de Python, pásalo en «Configuración» → «Lenguaje» (nace en Node.js), sube los ficheros en «Archivos» (o pon tu repositorio de GitHub, sin el .env, y sube el .env aparte) y pulsa «Encender». Las librerías se instalan solas al arrancar; app.py o index.js es el fichero de inicio que viene puesto.
El bot gratis tiene 256 MB, de sobra para un bot de bienvenida, y solo hay que renovarlo con un clic cada semana. Si no quieres acordarte, con el plan Mini (512 MB) no hay que renovar nada.
Preguntas frecuentes
¿Por qué mi bot de bienvenida no hace nada cuando entra alguien?
Casi siempre falta «Server Members Intent»: hay que encenderlo en el portal de desarrolladores (pestaña «Bot») y pedirlo en el código (intents.members en discord.py, GatewayIntentBits.GuildMembers en discord.js). Sin él, Discord no le avisa al bot de quién entra.
¿Por qué sale «Missing Permissions» al dar el rol?
Porque el rol del bot está por debajo del rol que intenta dar, o le falta «Manage Roles». En «Ajustes del servidor» → «Roles», sube el rol del bot por encima.
¿Hace falta un bot para dar la bienvenida en Discord?
Para un saludo aleatorio, no: Discord lo trae en los ajustes del servidor. Para tu propio mensaje, la foto, la mención o dar un rol a todo el que entra, sí.
¿Cómo hago que el rol se dé solo al aceptar las normas?
Esperando a que el miembro deje de estar pendiente (pending): el código de esta guía lo hace, con on_member_update en Python y GuildMemberUpdate en JavaScript.
¿Dónde tengo el bot de bienvenida encendido siempre?
En un servidor que no se apague. En NapNodes hay un bot gratis de 256 MB que solo hay que renovar con un clic cada semana.
¿Te ha servido esta guía?
¿Lo montamos?
Hosting de bots de Discord desde 1,50 € al mes, sin sobreventa: tu RAM es solo tuya. Y si quieres empezar sin pagar, tienes un bot de Discord gratis, sin tarjeta.
Herramienta gratis: Texto de colores en Discord. Escribe en Discord en rojo, verde o amarillo, con fondo, negrita y subrayado: el bloque ansi listo para pegar, y la línea para tu bot.
Sigue leyendo
- Bot de roles para Discord: botones para que cada uno elija sus roles (Python y JavaScript)
Haz tu bot de autoroles para Discord en Python o JavaScript: un mensaje con botones para ponerse y quitarse roles, sin base de datos y sin roles por reacción.
- Bot de verificación para Discord en Python: un botón y una pregunta antes de entrar
Haz tu bot de verificación de Discord con discord.py: botón «Verificarme», una pregunta contra bots y un rol que abre el servidor. Código completo y gratis.
- Bot de música para Discord: hazte el tuyo en Python o JavaScript
Por qué cerraron los bots de música de Discord y cómo hacer el tuyo con cola y /pon (discord.py o discord.js), con lo que pide la voz desde 2026.