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

# Autoposting your server count

> With a library you already use, or with six lines and setInterval.

The stats endpoint follows the field names every bot list uses — `server_count`,
with a bare token in the `Authorization` header — so a library that already
posts to several lists can add this one as configuration rather than as code.

## With a poster library

<CodeGroup>
  ```js blapi theme={null}
  const blapi = require('blapi');

  blapi.handle(client, {
    'discordbotlist.lol': process.env.DBL_TOKEN,
  });
  ```

  ```js @topgg/sdk style theme={null}
  // Any client that lets you set the base URL works the same way: the path and
  // the body are the ones this API documents.
  await fetch(`https://discordbotlist.lol/api/v1/bots/${botId}/stats`, {
    method: 'POST',
    headers: {
      Authorization: process.env.DBL_TOKEN,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ server_count: client.guilds.cache.size }),
  });
  ```
</CodeGroup>

## Without one

Six lines, and nothing to keep updated:

<CodeGroup>
  ```js discord.js theme={null}
  import { Client, Events } from 'discord.js';

  const client = new Client({ intents: [] });

  async function postCount() {
    const response = await fetch(
      `https://discordbotlist.lol/api/v1/bots/${process.env.BOT_ID}/stats`,
      {
        method: 'POST',
        headers: {
          Authorization: process.env.DBL_TOKEN,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ server_count: client.guilds.cache.size }),
      }
    );
    if (!response.ok) console.error('DBL stats', response.status);
  }

  client.once(Events.ClientReady, () => {
    postCount();
    // Every 30 minutes. The limit is 60 a minute; this is not a budget to spend.
    setInterval(postCount, 30 * 60 * 1000);
  });
  ```

  ```python discord.py theme={null}
  import os, aiohttp
  from discord.ext import tasks, commands

  bot = commands.Bot(command_prefix="!")

  @tasks.loop(minutes=30)
  async def post_count():
      async with aiohttp.ClientSession() as session:
          await session.post(
              f"https://discordbotlist.lol/api/v1/bots/{os.environ['BOT_ID']}/stats",
              headers={"Authorization": os.environ["DBL_TOKEN"]},
              json={"server_count": len(bot.guilds)},
          )

  @bot.event
  async def on_ready():
      post_count.start()
  ```
</CodeGroup>

## Sharding

Post the **total**, not the shard's slice. Each shard posting its own count
makes the number jump around as the shards check in, and the last one to post
wins. With `discord.js`:

```js theme={null}
const counts = await client.shard.fetchClientValues('guilds.cache.size');
const total = counts.reduce((sum, count) => sum + count, 0);
```

The 60-per-minute limit is high enough that a shard manager posting on behalf of
every shard has room to spare.

## How often

Every 15 to 30 minutes is plenty. Two things make a tighter interval pointless
rather than harmful:

* **Re-posting the same number is cheap on our side.** The page cache is only
  invalidated when the value actually changes, so an unchanged post costs one
  write and nothing else.
* **The check-in timestamp moves every time regardless.** It is the honest
  liveness signal on your listing, and it does not need a 30-second loop to stay
  true.

<Note>
  The count is **not** guessed from Discord. There is no documented endpoint for
  another application's guild count, so before this API existed the number was
  typed in by hand. Posting it is the only way your page shows a real one.
</Note>
