---
title: Variables
description: Everything that can go inside {curly braces} in a command response, timer message or announcement - and how to combine them.
---

Anywhere the bot speaks - [custom commands](/chat-bot/custom-commands),
[timers](/chat-bot/timers), [announcements](/chat-bot/announcements) - you
write the message once and the bot fills in the blanks. A blank is a
**variable**: a name in curly braces, sometimes with an argument after a
colon.

```text
{user}                a name, no argument
{random:1-100}        a name with an argument
{repeat:3|Kappa}      arguments with several parts use | between them
```

Variable names aren't case-sensitive. Anything the bot doesn't recognise
is left exactly as you typed it.

## Variables nest

An argument can contain other variables. The bot works from the inside
out, so this does what it looks like:

```text
!coinflip  →  {user} flipped a coin: {if:{random:0-1}==1|heads|tails}
```

`{random:0-1}` becomes `0` or `1` first, then `{if:}` looks at the result.
Anything you can build from smaller pieces, you can put inside a bigger
one - `{ai:...}` prompts, `{urlfetch:}` URLs, `{repeat:}` counts, all of
it.

## Viewer text is never code

`{args}`, `{arg:N}` and `{touser}` carry text a viewer typed. That text
is treated as **data**: if someone types `{pick:/ban|x}` at your bot, the
bot echoes their curly braces back rather than running them - even when
their text ends up inside an `{if:}` condition or an `{ai:}` prompt. The
same goes for anything fetched from outside (`{urlfetch:}`, `{ai:}`
replies). You can nest freely without worrying about what chat will
type.

## Twitch and Kick

Every variable works in both chats unless a page says otherwise. The
ones that read the chat itself (`{user}`, `{args}`, `{msgid}`, ...) use
whichever platform the message came from; the stream ones (`{uptime}`,
`{game}`, ...) read the channel the message came from and take a
`twitch:` / `kick:` argument to read the other. The exceptions, all
because Kick has no API for them:

| Variable | Twitch | Kick |
| --- | --- | --- |
| [`{accountage}`](/chat-bot/variables/accountage) | Yes | Blank |
| [`{emote}` / `{emotes}`](/chat-bot/variables/emotes) | Yes | Blank |
| [`{bttv}` / `{ffz}`](/chat-bot/variables/third-party-emotes) | Yes | Blank - both are Twitch-only products |
| [`{7tv}`](/chat-bot/variables/third-party-emotes) | Yes | Yes - 7TV serves Kick channels too |
| [`{user.*}`](/chat-bot/variables/user) (`messages`, `tipped`, `rank`, `last_seen`, ...) | Yes | Yes - chat stats are counted per platform and tips follow the viewer's linked accounts |
| [`{followage}`](/chat-bot/variables/followage) | Yes | Yes - best-effort, may read blank if Kick's lookup is unavailable |

## All variables

**Who and what**

| Variable | Becomes |
| --- | --- |
| [`{user}`](/chat-bot/variables/user) | The person who ran the command - plus `{user.messages}`, `{user.tipped}`, `{user.rank}`, `{user.last_seen}` and more |
| [`{touser}`](/chat-bot/variables/touser) | Who the command is aimed at - the first word typed, or the user if nothing was |
| [`{channel}`](/chat-bot/variables/channel) | Your channel name |
| [`{platform}`](/chat-bot/variables/platform) | `twitch` or `kick` - where the message is running |
| [`{args}`](/chat-bot/variables/args) | Everything the viewer typed after the command |
| [`{arg:N}`](/chat-bot/variables/arg) | The Nth word they typed |
| [`{msgid}`](/chat-bot/variables/msgid) | The platform's id for the message that triggered the command |

**Randomness**

| Variable | Becomes |
| --- | --- |
| [`{pick:a\|b\|c}`](/chat-bot/variables/pick) | One of the options |
| [`{list:name}`](/chat-bot/variables/list) | A random line from a response list |
| [`{random:1-100}`](/chat-bot/variables/random) | A random whole number in the range |

**Logic and text**

| Variable | Becomes |
| --- | --- |
| [`{if:a==b\|yes\|no}`](/chat-bot/variables/if) | One of two texts, depending on a comparison |
| [`{repeat:3\|text}`](/chat-bot/variables/repeat) | The text repeated |
| [`{upper:text}` / `{lower:text}`](/chat-bot/variables/upper-lower) | The text in capitals / lowercase |
| [`{queryescape:text}` / `{pathescape:text}`](/chat-bot/variables/queryescape-pathescape) | The text made safe for a URL |

**Your stream**

| Variable | Becomes |
| --- | --- |
| [`{uptime}`](/chat-bot/variables/uptime) | How long you've been live |
| [`{title}`](/chat-bot/variables/title) | Your stream title |
| [`{game}`](/chat-bot/variables/game) | The category you're streaming |
| [`{viewers}`](/chat-bot/variables/viewers) | Your current viewer count |
| [`{emote}` / `{emotes}`](/chat-bot/variables/emotes) | A random channel emote / all of them (Twitch only) |
| [`{7tv}` / `{bttv}` / `{ffz}`](/chat-bot/variables/third-party-emotes) | A random 7TV / BetterTTV / FrankerFaceZ emote - plus `.list` and `.count`, and any emote set you point them at |
| [`{followage}`](/chat-bot/variables/followage) | How long someone has followed you |
| [`{accountage}`](/chat-bot/variables/accountage) | How old someone's Twitch account is (Twitch only) |

**Your tips and queues**

| Variable | Becomes |
| --- | --- |
| [`{tips.today}`, `{tips.month}`, `{tips.total}`, …](/chat-bot/variables/tips) | Tip totals, the latest tip, your top supporter, your minimum and maximum tip |
| [`{tip_page}`](/chat-bot/variables/tip-page) | Your tip page address |
| [`{tts.queue}`, `{media.queue}`, `{media.now}`](/chat-bot/variables/queue) | What's queued and what's playing |

**Counters, the web, and AI**

| Variable | Becomes |
| --- | --- |
| [`{count}` / `{counter:name}`](/chat-bot/variables/count) | A counter that bumps on every use / a counter's current value |
| [`{urlfetch:https://...}`](/chat-bot/variables/urlfetch) | Whatever text that URL returns |
| [`{ai:prompt}`](/chat-bot/variables/ai) | A one-line reply from an AI model |

The **stream** and **counters / web / AI** groups fetch live data, so a
response using them takes a beat longer to appear - usually well under a
second, a couple of seconds for `{ai:}`.
