---
title: "Bots and Parties"
description: "Read bots, party members, and party or member meta."
canonical: "https://developers.fnlb.net/docs/sdk/parties"
markdown: "/docs/sdk/parties.md"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fnlb.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Bots and Parties

---
title: "Bots and parties"
sidebarTitle: "Bots and parties"
description: "Load a running bot, read its party, and get or set party and member meta."
icon: "smartToy"
---

A `Bot` exists only after its shard has logged it in. Read it from `fnlb.bots.cache` inside `Events.Ready`, or `await fnlb.bots.fetch(id)`. Party, chat, and commands on that object talk to the local shard. They throw if the local FNLB client does not support the SDK bridge.

```ts
fnlb.on(Events.Ready, async (bot) => {
  console.log(bot.id, bot.epicId, bot.displayName, bot.party.id);
});

const bot = await fnlb.bots.fetch('bot-id');
await bot.fetch();
```

`fetch()` asks the shard for a fresh snapshot and replaces party members and presence on the same object.

| Field | Meaning |
| :--- | :--- |
| `id` | FNLB bot id. Same id as `fnlb.api.bots.list()`. |
| `nickname` | Name in FNLB. |
| `epicId` / `displayName` | Epic account, after ready. |
| `parent` | Category id, when the bot has one. |
| `flags` | Bitfield from the API. 1 disabled, 2 public, 4 invalid auth, 8 prepared. |
| `ready` | True after the Fortnite client has logged in. |
| `friendsCount` / `presenceStatus` | Last friend count and presence string. |
| `party` | The party the bot is in. |

`fnlb.bots.cache` is a `Collection` (a `Map` with `find` and `filter`). It does not include bots that this process is not running.

## Party

`bot.party` is the Fortnite party.

| Member | Meaning |
| :--- | :--- |
| `id` | Epic party id. |
| `playlistId` | Island or playlist link id, lowercased. |
| `members` | `Collection` of `PartyMember`, keyed by Epic account id. Includes the bot. |
| `me` | The bot's own member, once `bot.epicId` is known. |
| `meta` | Party schema (playlist, privacy, custom key). |
| `fetchMembers()` | Reload `members` from the shard. |

Each [`PartyMember`](/sdk?symbol=PartyMember) has `id`, `displayName`, `isLeader`, `isReady`, `isSittingOut`, `isPlaying`, `outfit`, `emote`, `backpack`, `pickaxe`, `shoes`, `sidekick`, and `meta`. `kick()` and `promote()` on a member call the same party methods with that member's id.

`members` is a [`Collection`](/sdk?symbol=Collection): a `Map` plus `find` and `filter`.

```ts
const leader = bot.party.members.find((member) => member.isLeader);
const others = bot.party.members.filter((member) => member.id !== bot.epicId);
```

## Meta

Party meta and member meta are different schemas.

- `bot.party.meta` is the party (playlist, privacy, custom match key).
- `bot.party.me.meta` is the bot's own member (cosmetics and loadout on that member).
- `member.meta.get()` can read another member. `set()` on anyone except the bot throws.

```ts
await bot.party.meta.set('Default:CustomMatchKey_s', 'my-key');
const playlist = await bot.party.meta.get('Default:PlaylistData_j');
const all = await bot.party.me.meta.get();
```

`get()` with no key returns the parsed schema. `get(key)` returns one value. `set(key, value)` writes one key and sends that patch.

| Key suffix | Value |
| :--- | :--- |
| `j` | Object |
| `b` | Boolean |
| `U` | Number |
| `s` | String |

Events such as `PartyMemberOutfitUpdated` carry the cosmetic id, not this schema. Call `get()` when you need the full object.

## Lobby controls

These run on the live Fortnite client inside the shard. Privacy, playlist, fill, size, and hiding members require party leader. Cosmetics change only this bot. The FNLB client has to be current; an older client rejects `fortnite.action`.

```ts
import { PartyPrivacy, Playlist } from 'fnlb';

await bot.party.setPrivacy(PartyPrivacy.PUBLIC);
await bot.party.setPlaylist(Playlist.SQUAD, 'NAE');
await bot.party.setCustomMatchmakingKey('my-key');
await bot.party.setSquadFill(false);
await bot.party.setMaxSize(4);

await bot.party.me?.setOutfit('CID_028_Athena_Commando_F', [{ variantIndex: 1 }]);
await bot.party.setEmote('EID_Wave');
await bot.party.clearEmote();
await bot.party.setReady(true);
await bot.party.setSittingOut(false);
await bot.party.setBanner('OtherBanner', 'DefaultColor');
await bot.party.setBattlePass(true, 100);

await bot.setStatus('Lobby bot', 'online');
await bot.join('party-id');
await bot.requestToJoin('friend-epic-id');
```

`setPlaylist` takes a link id or island code. [`Playlist`](/sdk?symbol=Playlist) has the usual modes. Any other island code is a plain string, for example `1111-1111-1111`. The second argument is a region such as `NAE`. Omit it to keep the current region.

| `Playlist` | Link id |
| :--- | :--- |
| `SOLO` | `playlist_defaultsolo` |
| `DUO` | `playlist_defaultduo` |
| `TRIOS` | `playlist_trios` |
| `SQUAD` | `playlist_defaultsquad` |
| `CREATIVE` | `playlist_playgroundv2` |
| `LEGO` | `playlist_juno` |
| `ROCKET_RACING` | `playlist_delmar` |
| `FESTIVAL` | `playlist_sparksrhythm` |

[`PartyPrivacy`](/sdk?symbol=PartyPrivacy) is a name, not the numeric dashboard enum in [category config](/docs/sdk/category-config.md#general). `PUBLIC` is an open party. `PRIVATE` is invite-only. `FRIENDS` limits joins to the leader's friends. `FRIENDS_ALLOW_FRIENDS_OF_FRIENDS` and `PRIVATE_ALLOW_FRIENDS_OF_FRIENDS` loosen that.

`party.me.setOutfit` is the same call as `party.setOutfit`. It throws on any member that is not this bot. `variants` is a list of [`SdkCosmeticVariant`](/sdk?symbol=SdkCosmeticVariant): `{ variantIndex }` is the cosmetic style index, starting at 0.

| Method | What it sets | Reference |
| :--- | :--- | :--- |
| `setOutfit(id, variants?)` | Outfit | [`Party.setOutfit`](/sdk?symbol=Party#setoutfit) |
| `setBackpack` / `setPickaxe` / `setShoes` / `setSidekick` | That slot. Optional `path` is the game-file path. | [`Party`](/sdk?symbol=Party) |
| `clearBackpack` / `clearShoes` / `clearSidekick` | Remove that slot | [`Party`](/sdk?symbol=Party) |
| `setEmote` / `setEmoji` / `setTrack` | Emote, emoji, or jam track | [`Party.setEmote`](/sdk?symbol=Party#setemote) |
| `clearEmote()` | Stop the current emote, emoji, or track | [`Party.clearEmote`](/sdk?symbol=Party#clearemote) |
| `setReady(boolean)` | Ready up | [`Party.setReady`](/sdk?symbol=Party#setready) |
| `setSittingOut(boolean)` | Sit out | [`Party.setSittingOut`](/sdk?symbol=Party#setsittingout) |
| `setBanner(bannerId, color)` | Banner icon and color | [`Party.setBanner`](/sdk?symbol=Party#setbanner) |
| `setBattlePass(purchased, level)` | Pass ownership and level shown on the bot | [`Party.setBattlePass`](/sdk?symbol=Party#setbattlepass) |
| `setLevel(level)` | Account level shown on the bot | [`Party.setLevel`](/sdk?symbol=Party#setlevel) |
| `setCosmeticStats(crowns, ranked)` | Crown count and ranked progress | [`Party.setCosmeticStats`](/sdk?symbol=Party#setcosmeticstats) |
| `hideMembers(hide?)` / `hideMember(id, hide?)` | Hide other members in the squad list. Leader only. | [`Party.hideMembers`](/sdk?symbol=Party#hidemembers) |

`bot.setStatus(text, onlineType)` sets the presence friends see. `onlineType` is a [`PresenceOnlineType`](/sdk?symbol=PresenceOnlineType) value: `online`, `chat`, `away`, `xa`, or `dnd`. Omit the text to keep the current status.

`bot.join(partyId)` leaves the current party and joins another. `bot.requestToJoin(friendId)` asks to join a friend's party. They have to accept before this bot is invited. Invites you receive arrive as [`Events.PartyInvite`](/docs/sdk/events.md#party).

Dashboard outfits and privacy that should apply on every start belong in [category config](/docs/sdk/category-config.md), not in a `ready` listener.

## Party actions

The bot must already be friends with the target for an invite. Kick and promote require party leader.

```ts
await bot.party.invite('epic-account-id');
await bot.party.kick('epic-account-id');
await bot.party.promote('epic-account-id');
await bot.party.leave();
await bot.party.leave(false);
```

`leave()` defaults to creating a new party afterwards. Pass `false` to stay without one. `party.send(text)` writes in party chat. See [Chat and commands](/docs/sdk/chat-and-commands.md).

After `leave()`, `party.id` and `members` stay as the last snapshot until the next `fetch()`, `fetchMembers()`, or party event.

## Reference

| Topic | Symbol |
| :--- | :--- |
| Bot fields and `fetch` | [`Bot`](/sdk?symbol=Bot) |
| Party actions | [`Party`](/sdk?symbol=Party) |
| One member | [`PartyMember`](/sdk?symbol=PartyMember) |
| Schema read and write | [`PartyMeta`](/sdk?symbol=PartyMeta) |
| Privacy names | [`PartyPrivacy`](/sdk?symbol=PartyPrivacy) |
| Playlist ids | [`Playlist`](/sdk?symbol=Playlist) |
