Your bot needs three values from your Lavalink node: the host, the port and the password. The host and port are the Address on the node's Overview; the password is in application.yml. Your client library must support Lavalink version 4 and Discord's DAVE voice encryption, and the secure (SSL) option stays off.
- On the Lavalink server's Overview, copy the Address (host and port), and copy the password from
application.yml. - On your bot server's Bot tab, Environment, add
LAVALINK_HOST,LAVALINK_PORTandLAVALINK_PASSWORD. - Add the client code for your library (examples below), with the secure (SSL) option off.
- Restart the bot and check that it reports the node as connected.
Each step in detail below.
What every client asks for
| Setting | Value |
|---|---|
| Host | The part of Address before the colon, for example 203.0.113.10 |
| Port | The number after the colon |
| Password | The password: under lavalink:, server: in application.yml |
| Secure / SSL | Off: the node uses plain http and ws |
Where to find them: How to host a Lavalink server 24/7.

Use a client release that supports DAVE
Since 2 March 2026 Discord only lets voice clients that support its end-to-end encryption, the DAVE protocol, into voice channels (stage channels excepted). Lavalink supports DAVE from version 4.2.0, and your node runs 4.2.2. Lavalink's 4.2.0 release notes say the client must also be updated: it now has to send the voice channel ID to the node. An older client release still connects to the node, but Lavalink cannot open the voice connection, so nothing plays. The release of each common client to use, or any newer one:
| Client | Language | Use this release or newer |
|---|---|---|
| Shoukaku | Node.js | 4.3.0 (28 Feb 2026) |
| lavalink-client | Node.js | 2.9.7 (2 Mar 2026). DAVE work started in 2.9.3 (27 Feb 2026); its author calls 2.9.7 the first major release with DAVE. |
| Wavelink | Python | 3.5.1 (11 Apr 2026) |
| Lavalink.py | Python | 5.10.0 (28 Feb 2026) |
For other libraries, Lavalink's own client list has a DAVE column. With an older client, your node answers the voice update with a 400 error saying token, endpoint, sessionId and channelId must be provided in voice state. (A bot that connects to Discord voice itself, without Lavalink, gets Discord's close code 4017, E2EE/DAVE protocol required, instead.)
Keep the values out of your code
The examples below read LAVALINK_HOST, LAVALINK_PORT and LAVALINK_PASSWORD from the environment. If your bot runs on a PlayNHost bot plan:
- Open the bot server's Bot tab and click Environment.
- Under Add a variable, add
LAVALINK_HOSTandLAVALINK_PORT. AddLAVALINK_PASSWORDwith Keep this value secret ticked. - Restart the bot. The variables reach it when it starts.
More: How to set environment variables and secrets for your Discord bot.
Node.js with Shoukaku
Packages: discord.js and shoukaku (4.3.0 or newer).
const { Client, Events, GatewayIntentBits } = require('discord.js');
const { Shoukaku, Connectors } = require('shoukaku');
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] });
const nodes = [{
name: 'playnhost',
url: `${process.env.LAVALINK_HOST}:${process.env.LAVALINK_PORT}`,
auth: process.env.LAVALINK_PASSWORD,
}];
// Create it before client.login(): Shoukaku connects when the bot is ready.
const shoukaku = new Shoukaku(new Connectors.DiscordJS(client), nodes);
shoukaku.on('ready', (name) => console.log(`Lavalink node ${name} connected`));
shoukaku.on('error', (name, error) => console.error(`Lavalink node ${name}:`, error));
client.once(Events.ClientReady, () => console.log(`Logged in as ${client.user.tag}`));
client.login(process.env.DISCORD_TOKEN);
Shoukaku's documentation shows how to join a voice channel and play a track once the node is connected.
Python with Wavelink
Packages: discord.py and wavelink (3.5.1 or newer).
import os
import discord
import wavelink
from discord.ext import commands
class Bot(commands.Bot):
def __init__(self):
super().__init__(command_prefix="!", intents=discord.Intents.default())
async def setup_hook(self):
node = wavelink.Node(
uri=f"http://{os.environ['LAVALINK_HOST']}:{os.environ['LAVALINK_PORT']}",
password=os.environ["LAVALINK_PASSWORD"],
)
await wavelink.Pool.connect(nodes=[node], client=self)
async def on_wavelink_node_ready(self, payload: wavelink.NodeReadyEventPayload):
print(f"Lavalink node {payload.node.identifier} connected")
bot = Bot()
bot.run(os.environ["DISCORD_TOKEN"])
setup_hook runs once, before the bot connects; on_ready can run again after every reconnect, so do not connect the node there.
Other clients
Any client that supports Lavalink 4 and DAVE works the same way with the same three values, for example lavalink-client for discord.js or Lavalink.py for Python. A client written for Lavalink 3 cannot talk to a version 4 node.
It does not connect
- Connection refused or timed out: the host or port is wrong, or the node is stopped. Copy the Address again from Overview and check the console shows
Lavalink is ready to accept connections. 401orUnauthorized: the password does not matchapplication.yml. Copy it again without the quotes.- An SSL or TLS error: secure is on in your client. Switch it off, or use
http://instead ofhttps://. - It connects, then plays nothing: first check that your client release is not older than the one in the table above. Then: the bot needs Connect and Speak in the voice channel, and the node needs a source that can play what you asked: Lavalink errors and what they mean.
Still on a free public node? Public node or your own node compares the options.



