> For the complete documentation index, see [llms.txt](https://docs.membercounter.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.membercounter.app/counters-reference/number.md).

# Number

Apply number formatting to the given number.

The Number counter turns a value into a number so that number formatting applies to it. On its own it changes nothing you can see. Its whole job is to make **Use compact notation**, **Override default locale** and **Override default digits** work on a value the bot would otherwise treat as text.

**Availability:** every bot type. It makes no network requests, so it needs no API key and no environment variable when you [self-host](/self-hosting/configuration.md).

<figure><img src="https://1582170640-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lu2S5r7lKtu4IK5ucu9%2Fuploads%2Fgit-blob-56763824d4438c1a1a00f2b49316e721d73a37b2%2Fcounter-number-options.png?alt=media" alt="Number options"><figcaption><p>The Number counter panel, with a nested HTTP counter in the <strong>Number</strong> field</p></figcaption></figure>

Counters that return text even when the text looks like a number:

* [HTTP](/counters-reference/http.md) returns the value at your **Data path**. A quoted JSON field arrives as text; a bare JSON number already arrives as a number.
* [Reddit](/counters-reference/reddit.md) returns text when it is set to return the subreddit title; its member counts are already numbers.
* [Clock](/counters-reference/clock.md) and [Date](/counters-reference/date.md) return a formatted string.
* [Concat](/counters-reference/concat.md) and [Replace](/counters-reference/replace.md) always return text.

## Options

| Option     | What it does                      | Notes                                                                                       |
| ---------- | --------------------------------- | ------------------------------------------------------------------------------------------- |
| **Number** | The value to convert to a number. | One value only. Type a number into the box, or pick a counter from the same box to nest it. |

The **Number** field takes a [nested counter](/using-the-dashboard/nested-counters.md), which is the normal way to use this counter. The nested counter has to return a valid number.

## What it returns

The value read as a number.

| Input                           | Result                          |
| ------------------------------- | ------------------------------- |
| `1234`                          | `1234`                          |
| `12` (with spaces around it)    | `12`                            |
| `1e3`                           | `1000`                          |
| `0x10`                          | `16`                            |
| an empty string                 | `0`                             |
| `1,234`                         | not a number, the counter fails |
| `$99`                           | not a number, the counter fails |
| `99.4%`                         | not a number, the counter fails |
| the **Number** field left empty | not a number, the counter fails |

{% hint style="warning" %}
Thousands separators, currency symbols and percent signs are the usual cause of a broken Number counter. Strip the extra characters with a [Replace](/counters-reference/replace.md) counter nested inside the **Number** field first.
{% endhint %}

An empty string quietly becomes `0` instead of failing, so a nested counter that sometimes returns nothing shows `0` rather than an error.

Number does not round. `42.857142857142854` stays `42.857142857142854`, and **Use compact notation** is the only way to shorten a value.

## Formatting

This is the point of the counter, so all of the [Format settings](/using-the-dashboard/customizing-counters.md) apply: **Use compact notation**, **Override default locale**, and **Override default digits**, where you give each digit from 0 to 9 the character or emoji it is drawn with.

**Override default locale** only changes anything when **Use compact notation** is on. It picks the language the shortened form is written in.

{% hint style="warning" %}
The bot reads the formatting from the **outermost** counter of the chip, so Number has to be the outer counter for its own **Format settings** to matter. A Number counter buried inside a [Concat](/counters-reference/concat.md) or [Replace](/counters-reference/replace.md) counter only changes the value's type: the chip still ends up as text and the formatting is still skipped.
{% endhint %}

Custom digits only reach text and announcement channel topics, never voice or category channel names, because Discord channel names cannot show them.

## Refresh and caching

Number caches nothing. The bot works it out again on every channel update, every 10 minutes on the public bot and every 5 minutes on the other bot types. See [How counters update](/using-the-dashboard/how-counters-update.md).

Whatever you nest inside it keeps its own refresh behaviour, so an [HTTP](/counters-reference/http.md) counter with a **Lifetime (in seconds)** of `300` still only refetches every five minutes.

## Examples

{% tabs %}
{% tab title="Formatting a price from an API" %}
The Bitcoin price comes back from the API as text, so on its own it can never be shortened. Nesting it in a Number counter fixes that.

1. Add an [HTTP](/counters-reference/http.md) counter with **URL (GET)** `https://api.coinlore.net/api/ticker/?id=90`, **Data path** `[0].price_usd` and **Lifetime (in seconds)** `300`.
2. Add a **Number** counter and put the HTTP counter into its **Number** field, so Number is the outer counter.
3. Open **Format settings** on the Number counter and set **Use compact notation** to **Yes**.

The channel then shows the price shortened, such as `81K`, instead of the full number. Leave compact notation off and you get the raw number exactly as it came in.

<figure><img src="https://1582170640-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lu2S5r7lKtu4IK5ucu9%2Fuploads%2Fgit-blob-4c5863af032b704cecad1e5c055cb3639f003d88%2Fcounter-number-example-price.png?alt=media" alt="An HTTP price wrapped in a Number counter"><figcaption><p>HTTP fetches the price as text; the Number counter around it makes compact notation apply</p></figcaption></figure>
{% endtab %}

{% tab title="Fancy digits on a text value" %}
Custom digits are part of the number formatting, so the bot skips them for any counter that returns text. Put a Number counter around it, then turn on **Override default digits** in the outer counter's **Format settings** and set the character for each digit.

Remember that custom digits only show up in text and announcement channel topics.
{% endtab %}

{% tab title="Feeding Math" %}
[Math](/counters-reference/math.md) needs numbers. A value that arrives as text, such as an [HTTP](/counters-reference/http.md) JSON string or a [Reddit](/counters-reference/reddit.md) counter set to the subreddit title, has to go through a Number counter first.
{% endtab %}
{% endtabs %}

## Errors

| What you see                                                        | What to do                                                                                                                                                                                           |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The channel shows `ERROR!`                                          | The template failed. Open the channel in the dashboard and read the error below.                                                                                                                     |
| **Failed to generate a final string from the evaluation.**          | The value could not be read as a number. Refill the **Number** field, and clean commas, currency symbols or percent signs with a [Replace](/counters-reference/replace.md) counter nested inside it. |
| **The result for the channel name is less than 2 characters long.** | A voice or category channel name needs at least 2 characters. Add text around the counter in the template, for example `Members:` before it.                                                         |

If it still fails, [Troubleshooting](/using-the-dashboard/troubleshooting.md) covers the common causes, and you can ask on the [support server](https://membercounter.app/support).

<details>

<summary>Technical details</summary>

* Evaluator: `packages/services/src/DataSource/DataSourceEvaluator/evaluators/number.ts`, a single `Number(options.number)`, so the accepted inputs are the JavaScript coercion rules.
* `NaN` raises the known error `FAILED_TO_RETURN_A_FINAL_STRING`; the update job then writes `jobs.updateChannels.computeError` (`ERROR!` in en-US, translated in the other locales) into the name or topic.
* Why the counter is needed: a string result is returned untouched, and only a value that is already a number gets formatted.
* The format settings are taken once from the root counter's `format`, falling back to the guild's `formatSettings`, and forced onto every nested node, so a nested counter's own format is never read. The dashboard matches this and only ever writes the format of the outermost counter.
* Order of operations: compact notation through `Intl.NumberFormat(locale, { notation: "compact" })` first, then the custom-digit substitution, which runs only for GuildText and GuildAnnouncement channels.
* The dashboard preview evaluates with the real channel's type and falls back to GuildText only when the channel is not in the bot's cache, so the preview matches the channel.
* Global limits: 60 s per counter in the template, shared with everything nested inside it (`EVALUATION_TIMEOUT`), 50,000 tree-exploration iterations, and a final result that is trimmed and then cut to 1023 characters for a topic or 99 for a channel name, with the 2-character minimum (`EVALUATION_RESULT_FOR_CHANNEL_NAME_IS_LESS_THAN_2_CHARACTERS`) checked before the cut.
* No network access, no cache entry and no environment variable when self-hosting.

</details>
