or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-commands.mdchannels.mdclient.mdcommands.mderrors.mdevents.mdguild.mdindex.mdmessages.mdpermissions.mdtasks.mdui.mdusers.mdutilities.mdvoice.mdwebhooks.md

client.mddocs/

0

# Nextcord Client and Connection Management

1

2

## Overview

3

4

The nextcord library provides robust client classes for creating Discord bots with sophisticated connection management, event handling, and sharding capabilities. This documentation covers the core client classes and their connection management features.

5

6

## Client Class

7

8

The main bot client for Discord interactions, providing lifecycle management, event handling, and Discord API operations.

9

10

### Basic Client Setup { .api }

11

12

```python

13

import nextcord

14

from nextcord import Intents

15

16

# Basic client initialization

17

intents = Intents.default()

18

intents.message_content = True # Required for message content access

19

20

client = nextcord.Client(intents=intents)

21

22

@client.event

23

async def on_ready():

24

print(f'{client.user} has connected to Discord!')

25

26

# Run the client

27

client.run('your_bot_token')

28

```

29

30

### Client Constructor { .api }

31

32

```python

33

class Client:

34

def __init__(

35

self,

36

*,

37

max_messages: Optional[int] = 1000,

38

connector: Optional[aiohttp.BaseConnector] = None,

39

proxy: Optional[str] = None,

40

proxy_auth: Optional[aiohttp.BasicAuth] = None,

41

shard_id: Optional[int] = None,

42

shard_count: Optional[int] = None,

43

application_id: Optional[int] = None,

44

intents: Intents = Intents.default(),

45

member_cache_flags: MemberCacheFlags = MISSING,

46

chunk_guilds_at_startup: bool = MISSING,

47

status: Optional[Status] = None,

48

activity: Optional[BaseActivity] = None,

49

allowed_mentions: Optional[AllowedMentions] = None,

50

heartbeat_timeout: float = 60.0,

51

guild_ready_timeout: float = 2.0,

52

assume_unsync_clock: bool = True,

53

enable_debug_events: bool = False,

54

loop: Optional[asyncio.AbstractEventLoop] = None,

55

lazy_load_commands: bool = True,

56

rollout_associate_known: bool = True,

57

rollout_delete_unknown: bool = True,

58

rollout_register_new: bool = True,

59

rollout_update_known: bool = True,

60

rollout_all_guilds: bool = False,

61

default_guild_ids: Optional[List[int]] = None,

62

) -> None:

63

```

64

65

**Parameters:**

66

- `max_messages`: Maximum number of messages to store in cache (default: 1000, None disables)

67

- `intents`: Gateway intents controlling which events the bot receives

68

- `heartbeat_timeout`: Maximum seconds before timing out heartbeat (default: 60.0)

69

- `guild_ready_timeout`: Maximum seconds to wait for GUILD_CREATE stream (default: 2.0)

70

- `status`: Initial status upon login (online, idle, dnd, invisible)

71

- `activity`: Initial activity/presence upon login

72

- `allowed_mentions`: Global mention configuration for all messages

73

- `enable_debug_events`: Enable debug events like socket receive/send

74

- `shard_id`/`shard_count`: Manual sharding configuration (use AutoShardedClient instead)

75

76

## Lifecycle Methods

77

78

### Authentication and Connection { .api }

79

80

```python

81

# Login with bot token

82

async def login(self, token: str) -> None:

83

"""Logs in the client with the specified credentials."""

84

85

# Connect to Discord gateway

86

async def connect(self, *, reconnect: bool = True) -> None:

87

"""Creates websocket connection and handles events."""

88

89

# Combined login + connect

90

async def start(self, token: str, *, reconnect: bool = True) -> None:

91

"""Shorthand for login() followed by connect()."""

92

93

# Blocking run method

94

def run(self, token: str, *, reconnect: bool = True) -> None:

95

"""Blocking call that handles the event loop automatically."""

96

```

97

98

### Connection Management { .api }

99

100

```python

101

# Close connection

102

async def close(self) -> None:

103

"""Closes the connection to Discord."""

104

105

# Clear internal state for reconnection

106

def clear(self) -> None:

107

"""Clears internal state - bot can be considered 're-opened'."""

108

109

# Check connection status

110

def is_closed(self) -> bool:

111

"""Returns True if the websocket connection is closed."""

112

113

def is_ready(self) -> bool:

114

"""Returns True if the client's internal cache is ready."""

115

116

# Wait for ready state

117

async def wait_until_ready(self) -> None:

118

"""Waits until the client's internal cache is ready."""

119

```

120

121

## Connection State Properties { .api }

122

123

```python

124

@property

125

def latency(self) -> float:

126

"""Latency between HEARTBEAT and HEARTBEAT_ACK in seconds."""

127

128

@property

129

def user(self) -> Optional[ClientUser]:

130

"""The connected client user. None if not logged in."""

131

132

@property

133

def guilds(self) -> List[Guild]:

134

"""Guilds the connected client is a member of."""

135

136

@property

137

def voice_clients(self) -> List[VoiceProtocol]:

138

"""List of voice connections (usually VoiceClient instances)."""

139

140

def is_ws_ratelimited(self) -> bool:

141

"""Whether the websocket is currently rate limited."""

142

```

143

144

### Data Fetching Methods { .api }

145

146

Core methods for fetching Discord objects by ID, bypassing local cache for fresh data from Discord's API.

147

148

```python

149

async def fetch_user(self, user_id: int, /) -> User:

150

"""

151

Retrieves a User based on their ID from Discord's API.

152

153

Parameters:

154

- user_id: The ID of the user to fetch

155

156

Returns:

157

User: The user object

158

159

Raises:

160

NotFound: User not found

161

HTTPException: Fetching failed

162

"""

163

164

async def fetch_guild(self, guild_id: int, /, *, with_counts: bool = True) -> Guild:

165

"""

166

Retrieves a Guild by ID from Discord's API.

167

168

Parameters:

169

- guild_id: The ID of the guild to fetch

170

- with_counts: Whether to include approximate member/presence counts

171

172

Returns:

173

Guild: The guild object

174

"""

175

176

async def fetch_channel(self, channel_id: int, /) -> Union[GuildChannel, PrivateChannel, Thread]:

177

"""

178

Retrieves a Channel by ID from Discord's API.

179

180

Parameters:

181

- channel_id: The ID of the channel to fetch

182

183

Returns:

184

Union[GuildChannel, PrivateChannel, Thread]: The channel object

185

"""

186

187

async def fetch_guild_preview(self, guild_id: int, /) -> GuildPreview:

188

"""

189

Retrieves a GuildPreview for a public guild.

190

191

Parameters:

192

- guild_id: The ID of the guild to preview

193

194

Returns:

195

GuildPreview: The guild preview

196

"""

197

```

198

199

### Application Command Management { .api }

200

201

Methods for managing and syncing application commands across Discord.

202

203

```python

204

async def sync_all_application_commands(

205

self,

206

data: Optional[Dict[Optional[int], List[ApplicationCommandPayload]]] = None,

207

*,

208

use_rollout: bool = True,

209

associate_known: bool = True,

210

delete_unknown: bool = True,

211

) -> None:

212

"""

213

Syncs all application commands with Discord.

214

215

Parameters:

216

- data: Optional command data to sync

217

- use_rollout: Whether to use command rollout features

218

- associate_known: Whether to associate known commands

219

- delete_unknown: Whether to delete unknown commands from Discord

220

"""

221

222

async def deploy_application_commands(

223

self,

224

*,

225

guild_id: Optional[int] = None,

226

use_rollout: bool = True,

227

) -> None:

228

"""

229

Deploys application commands to Discord.

230

231

Parameters:

232

- guild_id: Optional guild ID to deploy to (None for global)

233

- use_rollout: Whether to use rollout features

234

"""

235

```

236

237

## Event System

238

239

### Event Registration { .api }

240

241

```python

242

# Decorator for event registration

243

def event(self, coro: Callable) -> Callable:

244

"""Decorator to register an event listener."""

245

246

@client.event

247

async def on_message(message):

248

if message.author == client.user:

249

return

250

if message.content.startswith('!hello'):

251

await message.channel.send('Hello!')

252

253

# Wait for specific events

254

async def wait_for(

255

self,

256

event: str,

257

*,

258

check: Optional[Callable[..., bool]] = None,

259

timeout: Optional[float] = None,

260

) -> Any:

261

"""Waits for a WebSocket event to be dispatched."""

262

263

# Example: Wait for user response

264

@client.event

265

async def on_message(message):

266

if message.content == '!question':

267

await message.channel.send('What is your favorite color?')

268

269

def check(m):

270

return m.author == message.author and m.channel == message.channel

271

272

try:

273

response = await client.wait_for('message', check=check, timeout=30.0)

274

await message.channel.send(f'Your favorite color is {response.content}!')

275

except asyncio.TimeoutError:

276

await message.channel.send('You took too long to respond!')

277

```

278

279

### Event Dispatch { .api }

280

281

```python

282

def dispatch(self, event: str, *args: Any, **kwargs: Any) -> None:

283

"""Dispatches an event to registered listeners."""

284

285

# Error handling

286

async def on_error(self, event_method: str, *args: Any, **kwargs: Any) -> None:

287

"""Default error handler - override for custom error handling."""

288

```

289

290

## AutoShardedClient

291

292

Automatically manages multiple shards for large bots (1000+ guilds).

293

294

### AutoShardedClient Setup { .api }

295

296

```python

297

import nextcord

298

from nextcord import AutoShardedClient, Intents

299

300

intents = Intents.default()

301

intents.message_content = True

302

303

# Automatic sharding - library determines shard count

304

client = AutoShardedClient(intents=intents)

305

306

# Manual shard configuration

307

client = AutoShardedClient(

308

intents=intents,

309

shard_count=4,

310

shard_ids=[0, 1] # Only run shards 0 and 1

311

)

312

313

@client.event

314

async def on_ready():

315

print(f'Logged in as {client.user}')

316

print(f'Shard count: {len(client.shards)}')

317

for shard_id, shard in client.shards.items():

318

print(f'Shard {shard_id}: {shard.latency:.2f}s latency')

319

320

client.run('your_bot_token')

321

```

322

323

### AutoShardedClient Constructor { .api }

324

325

```python

326

class AutoShardedClient(Client):

327

def __init__(

328

self,

329

*,

330

shard_ids: Optional[List[int]] = None,

331

shard_count: Optional[int] = None,

332

# ... all Client parameters ...

333

) -> None:

334

```

335

336

**Additional Parameters:**

337

- `shard_ids`: Specific shard IDs to launch (requires shard_count)

338

- `shard_count`: Total number of shards (auto-detected if None)

339

340

### Shard Management { .api }

341

342

```python

343

# Shard information access

344

@property

345

def shards(self) -> Dict[int, ShardInfo]:

346

"""Mapping of shard IDs to ShardInfo objects."""

347

348

def get_shard(self, shard_id: int) -> Optional[ShardInfo]:

349

"""Gets shard information for a specific shard ID."""

350

351

@property

352

def latency(self) -> float:

353

"""Average latency across all shards."""

354

355

@property

356

def latencies(self) -> List[Tuple[int, float]]:

357

"""List of (shard_id, latency) tuples for all shards."""

358

359

# Per-shard presence changes

360

async def change_presence(

361

self,

362

*,

363

activity: Optional[BaseActivity] = None,

364

status: Optional[Status] = None,

365

shard_id: Optional[int] = None, # None = all shards

366

) -> None:

367

"""Changes presence for specific shard or all shards."""

368

```

369

370

### ShardInfo Class { .api }

371

372

```python

373

class ShardInfo:

374

"""Information and control over a specific shard."""

375

376

@property

377

def id(self) -> int:

378

"""The shard ID."""

379

380

@property

381

def shard_count(self) -> Optional[int]:

382

"""Total shard count for this cluster."""

383

384

@property

385

def latency(self) -> float:

386

"""Latency for this specific shard."""

387

388

def is_closed(self) -> bool:

389

"""Whether the shard connection is closed."""

390

391

def is_ws_ratelimited(self) -> bool:

392

"""Whether this shard's websocket is rate limited."""

393

394

async def disconnect(self) -> None:

395

"""Disconnects this shard."""

396

397

async def reconnect(self) -> None:

398

"""Disconnects and reconnects this shard."""

399

400

async def connect(self) -> None:

401

"""Connects this shard if disconnected."""

402

```

403

404

## Connection Management

405

406

### Gateway Connection { .api }

407

408

The client uses WebSocket connections to Discord's gateway for real-time events.

409

410

```python

411

# Connection properties

412

@property

413

def ws(self) -> Optional[DiscordWebSocket]:

414

"""Current websocket gateway connection."""

415

416

# Rate limiting

417

def is_ws_ratelimited(self) -> bool:

418

"""Check if websocket is rate limited."""

419

420

# Reconnection handling

421

async def connect(self, *, reconnect: bool = True) -> None:

422

"""

423

Connect with automatic reconnection handling.

424

425

Parameters:

426

- reconnect: Whether to attempt reconnection on failure

427

"""

428

```

429

430

### Connection Events { .api }

431

432

```python

433

# Connection lifecycle events

434

@client.event

435

async def on_connect():

436

"""Called when client connects to Discord."""

437

438

@client.event

439

async def on_ready():

440

"""Called when client is ready to receive events."""

441

442

@client.event

443

async def on_disconnect():

444

"""Called when client disconnects from Discord."""

445

446

@client.event

447

async def on_resume():

448

"""Called when websocket resumes a previous connection."""

449

450

# Shard-specific events (AutoShardedClient only)

451

@client.event

452

async def on_shard_connect(shard_id: int):

453

"""Called when a shard connects."""

454

455

@client.event

456

async def on_shard_ready(shard_id: int):

457

"""Called when a shard is ready."""

458

459

@client.event

460

async def on_shard_disconnect(shard_id: int):

461

"""Called when a shard disconnects."""

462

463

@client.event

464

async def on_shard_resume(shard_id: int):

465

"""Called when a shard resumes."""

466

```

467

468

## Configuration Options

469

470

### Intents Configuration { .api }

471

472

Intents control which gateway events your bot receives. Configure them based on your bot's needs.

473

474

```python

475

from nextcord import Intents

476

477

# Default intents (recommended starting point)

478

intents = Intents.default() # Excludes privileged intents

479

480

# All intents (requires privileged intents approval)

481

intents = Intents.all()

482

483

# No intents

484

intents = Intents.none()

485

486

# Custom intent configuration

487

intents = Intents.default()

488

intents.members = True # Privileged - member events

489

intents.presences = True # Privileged - presence updates

490

intents.message_content = True # Privileged - message content access

491

intents.guilds = True # Guild events (recommended)

492

intents.guild_messages = True # Guild message events

493

intents.dm_messages = True # DM message events

494

intents.guild_reactions = True # Reaction events

495

intents.voice_states = True # Required for voice features

496

```

497

498

### Intent Flags Reference { .api }

499

500

```python

501

class Intents:

502

# Basic intents

503

guilds: bool # Guild events (join, leave, updates)

504

guild_messages: bool # Guild message events

505

dm_messages: bool # Direct message events

506

guild_reactions: bool # Guild reaction events

507

dm_reactions: bool # DM reaction events

508

guild_typing: bool # Guild typing events

509

dm_typing: bool # DM typing events

510

511

# Privileged intents (require approval for verified bots)

512

members: bool # Member join/leave/update events

513

presences: bool # Member presence/status updates

514

message_content: bool # Access to message content

515

516

# Other intents

517

moderation: bool # Moderation events (bans, audit logs)

518

emojis_and_stickers: bool # Emoji and sticker events

519

integrations: bool # Integration events

520

webhooks: bool # Webhook events

521

invites: bool # Invite create/delete events

522

voice_states: bool # Voice state updates (required for voice)

523

guild_scheduled_events: bool # Scheduled event updates

524

auto_moderation_configuration: bool # Auto-mod rule changes

525

auto_moderation_execution: bool # Auto-mod actions

526

527

# Convenience properties

528

messages: bool # Both guild_messages and dm_messages

529

reactions: bool # Both guild_reactions and dm_reactions

530

typing: bool # Both guild_typing and dm_typing

531

auto_moderation: bool # Both auto_moderation intents

532

```

533

534

### Presence Configuration { .api }

535

536

```python

537

from nextcord import Status, Activity, ActivityType

538

539

# Status configuration

540

client = nextcord.Client(

541

status=Status.idle, # online, idle, dnd, invisible

542

activity=Activity(type=ActivityType.playing, name="with the Discord API")

543

)

544

545

# Change presence after connection

546

await client.change_presence(

547

status=Status.dnd,

548

activity=Activity(type=ActivityType.listening, name="user commands")

549

)

550

551

# Activity types

552

ActivityType.playing # "Playing {name}"

553

ActivityType.listening # "Listening to {name}"

554

ActivityType.watching # "Watching {name}"

555

ActivityType.competing # "Competing in {name}"

556

ActivityType.streaming # "Streaming {name}" (requires url)

557

ActivityType.custom # Custom status

558

```

559

560

### Message Cache Configuration { .api }

561

562

```python

563

# Configure message caching

564

client = nextcord.Client(

565

max_messages=5000, # Cache up to 5000 messages

566

# max_messages=None, # Disable message caching

567

# max_messages=0, # No message caching

568

)

569

570

# Access cached messages

571

@client.event

572

async def on_ready():

573

print(f"Cached {len(client.cached_messages)} messages")

574

for message in client.cached_messages:

575

print(f"{message.author}: {message.content}")

576

```

577

578

### Advanced Configuration { .api }

579

580

```python

581

import aiohttp

582

583

# Advanced client configuration

584

connector = aiohttp.TCPConnector(limit=100)

585

586

client = nextcord.Client(

587

connector=connector, # Custom aiohttp connector

588

proxy="http://proxy.example.com:8080", # HTTP proxy

589

proxy_auth=aiohttp.BasicAuth("user", "pass"), # Proxy authentication

590

heartbeat_timeout=90.0, # Heartbeat timeout (seconds)

591

guild_ready_timeout=5.0, # Guild ready timeout (seconds)

592

assume_unsync_clock=False, # Use system clock for rate limits

593

enable_debug_events=True, # Enable socket debug events

594

chunk_guilds_at_startup=False, # Don't chunk members at startup

595

)

596

597

# Member cache configuration

598

from nextcord import MemberCacheFlags

599

600

member_cache = MemberCacheFlags.all()

601

member_cache.joined = False # Don't cache join times

602

603

client = nextcord.Client(

604

intents=intents,

605

member_cache_flags=member_cache

606

)

607

```

608

609

## Connection Hooks

610

611

### Before Identify Hook { .api }

612

613

```python

614

# Customize identify behavior (useful for large bots)

615

async def before_identify_hook(self, shard_id: Optional[int], *, initial: bool = False) -> None:

616

"""

617

Called before IDENTIFY for each shard.

618

619

Parameters:

620

- shard_id: The shard ID being identified

621

- initial: Whether this is the first IDENTIFY

622

"""

623

if not initial:

624

await asyncio.sleep(5.0) # Default: wait 5 seconds between identifies

625

626

# Custom logic for identify timing

627

if shard_id is not None and shard_id > 0:

628

await asyncio.sleep(shard_id * 2) # Staggered identification

629

```

630

631

## Error Handling

632

633

### Connection Errors { .api }

634

635

```python

636

from nextcord import ConnectionClosed, GatewayNotFound, PrivilegedIntentsRequired

637

638

try:

639

await client.start(token)

640

except ConnectionClosed as e:

641

print(f"Connection closed: {e.code} - {e.reason}")

642

except GatewayNotFound:

643

print("Could not find Discord gateway (API outage?)")

644

except PrivilegedIntentsRequired as e:

645

print(f"Privileged intents required for shard {e.shard_id}")

646

647

# Custom error handling

648

@client.event

649

async def on_error(event, *args, **kwargs):

650

import traceback

651

print(f'Error in {event}:')

652

traceback.print_exc()

653

```

654

655

## Best Practices

656

657

### Production Setup { .api }

658

659

```python

660

import logging

661

import nextcord

662

from nextcord import Intents

663

664

# Configure logging

665

logging.basicConfig(level=logging.INFO)

666

667

# Production client setup

668

intents = Intents.default()

669

intents.message_content = True # Only if needed

670

671

client = nextcord.Client(

672

intents=intents,

673

max_messages=1000, # Reasonable message cache

674

heartbeat_timeout=60.0, # Default heartbeat timeout

675

chunk_guilds_at_startup=False, # Faster startup for large bots

676

)

677

678

@client.event

679

async def on_ready():

680

logging.info(f'{client.user} is ready!')

681

logging.info(f'Latency: {client.latency:.2f}s')

682

logging.info(f'Guilds: {len(client.guilds)}')

683

684

@client.event

685

async def on_error(event, *args, **kwargs):

686

logging.exception(f'Error in event {event}')

687

688

# Graceful shutdown

689

import signal

690

691

def signal_handler(signum, frame):

692

logging.info('Received shutdown signal')

693

client.loop.create_task(client.close())

694

695

signal.signal(signal.SIGINT, signal_handler)

696

signal.signal(signal.SIGTERM, signal_handler)

697

698

client.run(token)

699

```

700

701

### Large Bot Configuration { .api }

702

703

```python

704

# For bots in 1000+ guilds

705

from nextcord import AutoShardedClient, Intents

706

707

intents = Intents.default()

708

intents.members = False # Disable if not needed (reduces memory)

709

intents.presences = False # Disable if not needed (reduces memory)

710

intents.message_content = True # Only if needed

711

712

client = AutoShardedClient(

713

intents=intents,

714

max_messages=500, # Lower message cache per shard

715

chunk_guilds_at_startup=False, # Essential for large bots

716

member_cache_flags=MemberCacheFlags.none(), # Minimize memory usage

717

)

718

719

@client.event

720

async def on_ready():

721

total_guilds = len(client.guilds)

722

shard_count = len(client.shards)

723

avg_latency = client.latency

724

725

print(f'Bot ready: {total_guilds} guilds across {shard_count} shards')

726

print(f'Average latency: {avg_latency:.2f}s')

727

728

# Log per-shard info

729

for shard_id, shard in client.shards.items():

730

guilds_on_shard = len([g for g in client.guilds if g.shard_id == shard_id])

731

print(f'Shard {shard_id}: {guilds_on_shard} guilds, {shard.latency:.2f}s latency')

732

733

client.run(token)

734

```

735

736

This comprehensive guide covers all aspects of nextcord's client and connection management capabilities, providing both basic usage examples and advanced configuration options for production deployments.