# How to build a Telegram AI bot with Claude, GPT or Gemini

> Create a Telegram bot in BotFather and answer messages with Claude, GPT or Gemini through an OpenAI-compatible API, with tested Python code and costs.

Updated: 2026-11-01

Create the bot in @BotFather to get its token, then run a short Python script that sends each message to a chat model and posts the answer back. With a 5abeer key, the OpenAI SDK reaches Claude, GPT and Gemini models below official prices, and you pay only for the tokens each answer uses.

## What do you need to build a Telegram AI bot?

- A Telegram account, to create the bot in @BotFather and get its token.
- A 5abeer API key for the provider the bot will use. The code below uses the default model, [`claude-sonnet-5.5`](https://5abeer.ai/en/models/claude-sonnet-5.5), so it needs a Claude key. The steps are in [Create a key](https://5abeer.ai/en/docs/start/keys.md#create), and the basics are in [How to get an API key for Claude, GPT and Gemini](https://5abeer.ai/en/guides/ai-api-key-guide).
- Python 3.10 or later, with two packages: the official `openai` SDK and `requests`.
- A computer or server that stays on while the bot runs.

## How do you get a bot token from BotFather?

### 1. Start a new bot

Open a chat with @BotFather in Telegram and send `/newbot`.

### 2. Pick a name and a username

The name is what people see in the chat. The username is the bot's address, as in `t.me/username`. It must be 5 to 32 characters long, use only Latin letters, digits and underscores, and end in `bot`, for example `support_helper_bot`.

### 3. Copy the token

BotFather replies with the bot's token. Telegram's advice is direct: "Keep your token secure and store it safely, it can be used by anyone to control your bot." If the token leaks, send `/token` to BotFather to generate a new one.

## How do you connect the bot to Claude, GPT or Gemini?

5abeer speaks the OpenAI Chat Completions format, so the bot uses the official OpenAI SDK with two changes: the base URL and the key. The same code reaches Claude, GPT and Gemini models. Only the model id and the key's provider change. Moving from another OpenAI-compatible service is the same switch, as in [An OpenRouter alternative below official prices](https://5abeer.ai/en/guides/openrouter-alternative).

| Format | Base URL | Key header |
| --- | --- | --- |
| OpenAI | `https://api.5abeer.ai/v1` | `Authorization: Bearer <KEY>` |
| Anthropic | `https://api.5abeer.ai` | `x-api-key: <KEY>` |
| Gemini | `https://api.5abeer.ai/v1beta` | `x-goog-api-key: <KEY>` |

Before running the bot, send one test request with your key. If it answers, the key and the model are ready. The format is explained in [Chat Completions](https://5abeer.ai/en/docs/api/chat-completions.md#quick).

```bash
curl --request POST "https://api.5abeer.ai/v1/chat/completions" \
  --header "Authorization: Bearer $KHABEER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"model":"claude-sonnet-5.5","messages":[{"role":"user","content":"Write a product idea in one sentence."}]}'
```

```python
import os
import requests

response = requests.post(
    "https://api.5abeer.ai/v1/chat/completions",
    headers={
        "Authorization": f"Bearer {os.environ['KHABEER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
    "model": "claude-sonnet-5.5",
    "messages": [
        {
            "role": "user",
            "content": "Write a product idea in one sentence."
        }
    ]
},
    stream=False,
    timeout=60,
)

response.raise_for_status()
print(response.json())
```

## What does the full bot look like?

The whole bot is one Python file. It uses long polling, so it needs no domain, certificate or open port. It answers only the chats you allow.

```python
import os
import time

import requests
from openai import OpenAI

TELEGRAM = "https://api.telegram.org/bot" + os.environ["TELEGRAM_BOT_TOKEN"]
client = OpenAI(api_key=os.environ["KHABEER_API_KEY"], base_url="https://api.5abeer.ai/v1")
MODEL = os.environ.get("BOT_MODEL", "claude-sonnet-5.5")
# Chat ids that may use the bot, comma-separated. "*" opens it to everyone.
ALLOWED = {x.strip() for x in os.environ.get("ALLOWED_CHAT_IDS", "").split(",") if x.strip()}

SYSTEM = "You are a helpful assistant. Answer briefly, in plain text, in the user's language."
GREETING = "Hi! Send me a question"
SORRY = "Sorry, I could not answer right now. Try again in a minute"
MAX_HISTORY = 10  # messages kept per chat: the last 5 questions and answers
history = {}


def telegram(method, **params):
    r = requests.post(f"{TELEGRAM}/{method}", json=params, timeout=60)
    r.raise_for_status()
    return r.json()["result"]


def send(chat_id, text):
    # Telegram accepts up to 4096 characters per message, so long answers go in parts.
    for i in range(0, len(text), 4000):
        telegram("sendMessage", chat_id=chat_id, text=text[i : i + 4000])


def handle(message):
    chat_id = message["chat"]["id"]
    text = message.get("text")
    if not text:
        return
    if "*" not in ALLOWED and str(chat_id) not in ALLOWED:
        print(f"ignored chat {chat_id}: add it to ALLOWED_CHAT_IDS")
        return
    if text.startswith(("/start", "/reset")):
        history.pop(chat_id, None)
        send(chat_id, GREETING)
        return
    telegram("sendChatAction", chat_id=chat_id, action="typing")
    past = history.get(chat_id, [])
    question = {"role": "user", "content": text}
    try:
        reply = client.chat.completions.create(
            model=MODEL,
            messages=[{"role": "system", "content": SYSTEM}, *past, question],
            max_tokens=1000,
        )
        answer = (reply.choices[0].message.content or "").strip()
    except Exception as error:
        print(f"model error: {error}")
        answer = ""
    if not answer:
        send(chat_id, SORRY)
        return
    history[chat_id] = (past + [question, {"role": "assistant", "content": answer}])[-MAX_HISTORY:]
    send(chat_id, answer)


def main():
    offset = 0
    while True:
        try:
            updates = telegram("getUpdates", offset=offset, timeout=50, allowed_updates=["message"])
        except requests.RequestException as error:
            print(f"telegram error: {error}")
            time.sleep(5)
            continue
        for update in updates:
            offset = update["update_id"] + 1
            if "message" in update:
                try:
                    handle(update["message"])
                except Exception as error:
                    print(f"update {update['update_id']} failed: {error}")


if __name__ == "__main__":
    main()
```

We tested this file on 2026-11-01 with Python 3.11 and the `openai` SDK 2.32 and 3.42, against local stand-ins for Telegram and the API, using a fake token and key.

## How do you run it and keep strangers out?

Anyone who finds the bot's username can message it, and every answer is paid from your balance. That is why the bot answers only the chat ids listed in `ALLOWED_CHAT_IDS`, and nobody when the list is empty.

```bash
pip install openai requests
export TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN"
export KHABEER_API_KEY="YOUR_5ABEER_API_KEY"
python3 bot.py
```

```powershell
pip install openai requests
$env:TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN"
$env:KHABEER_API_KEY="YOUR_5ABEER_API_KEY"
python bot.py
```

1. Start the bot and send it any message from your Telegram account.
2. The terminal prints `ignored chat 123456789: add it to ALLOWED_CHAT_IDS` with your real chat id.
3. Stop the bot, set `ALLOWED_CHAT_IDS` to that id the same way you set the key, and start it again.

Separate several ids with commas. The value `*` opens the bot to everyone, so set a spend limit on the key first.

## How does the code work?

- Long polling: `getUpdates` waits up to 50 seconds for new messages. The `offset` tells Telegram which updates are already handled, so none is answered twice.
- Typing status: Telegram shows it for up to 5 seconds, or until the reply arrives.
- Memory: the bot keeps the last 10 messages of each chat and sends them with every question, so follow-up questions work. `/start` or `/reset` clears that chat's memory, and so does a restart.
- Long answers: Telegram accepts 4,096 characters per message, so the bot sends longer answers in parts of 4,000.
- Plain text: the bot sets no `parse_mode`, and the system prompt asks for plain text, so answers rarely show stray Markdown symbols.
- Errors: the SDK retries rate limits, timeouts and server errors twice on its own. If a request still fails, the bot logs the error and sends a short apology instead of stopping.
- `max_tokens=1000` caps the answer length for Claude and Gemini models. GPT models ignore it, as listed in [Parameters](https://5abeer.ai/en/docs/api/chat-completions.md#params).

## How do you keep the bot running?

Long polling needs only outgoing connections, so any machine that stays on will do: a small cloud server, a home server or a container. Run it under a service manager such as systemd, or give the container a restart policy, so the bot comes back after a crash or a reboot.

Run one copy per token. Two copies polling the same bot compete for the same messages. If the bot is down for a while, Telegram keeps undelivered updates for up to 24 hours and the bot catches up when it returns.

The other way to receive messages is a webhook: Telegram sends each update to your HTTPS address. Set it with `setWebhook`, on port 443, 80, 88 or 8443. Add a `secret_token` and check the `X-Telegram-Bot-Api-Secret-Token` header on every request. While a webhook is set, `getUpdates` doesn't work, and `deleteWebhook` switches back to polling.

## What limits does Telegram set?

Telegram Bot API, version 10.3, checked on 2026-11-01:

| Limit | Value |
| --- | --- |
| Text per message | 1 to 4,096 characters |
| Messages to one chat | Avoid more than 1 per second; bursts end in 429 errors |
| Messages to one group | No more than 20 per minute |
| Messages to many users | About 30 per second, unless you pay for faster broadcasts |
| Files the bot downloads | Up to 20 MB |
| Files the bot sends | Up to 50 MB |
| Undelivered updates | Kept for up to 24 hours |

The group limit matters most for an AI bot. A long answer sent in three parts counts as three messages.

## How much does a Telegram AI bot cost?

Telegram itself doesn't charge for normal bot messages. Its FAQ says that "by default, bots are able to message their users at no cost". It charges Telegram Stars only for paid broadcasts above the normal rate. So the costs are the server and the model's tokens.

Each question sends the system prompt, the chat's memory and the new message. In this example, a bot answers 3,000 questions a month, at about 1,000 tokens in and 250 tokens out each:

Example: 3,000,000 input tokens and 750,000 output tokens on Claude Sonnet 5.5 (`claude-sonnet-5.5`) cost $4.05 at our price against $13.50 at the official price (70% lower). Official price checked October 19, 2026.

The price per token for the default model:

Claude Sonnet 5.5 (`claude-sonnet-5.5`) per 1M tokens: input $0.60 (official $2), output $3 (official $10). Official price checked October 19, 2026.

To spend less, pick a smaller model from the [models list](https://5abeer.ai/en/models) and use a key for its provider, lower `MAX_HISTORY` or lower `max_tokens`. You can compare providers on the [API page](https://5abeer.ai/en/api) and the [Claude API page](https://5abeer.ai/en/api/claude), and plan prices on the [pricing page](https://5abeer.ai/en/pricing).

Give the bot its own key with a spend limit, as in [Key controls](https://5abeer.ai/en/docs/start/keys.md#controls). When the key reaches the limit, requests fail with [`API_KEY_QUOTA_EXHAUSTED`](https://5abeer.ai/en/docs/help/errors.md#API_KEY_QUOTA_EXHAUSTED) and the bot sends its apology, so it stops spending at the limit you set.

## How do you keep the token and key safe?

- Keep both in environment variables. Never write them into the code or commit them to a repository.
- Use a separate key for the bot, with a spend limit and, if the server has a fixed address, an IP allow-list. The details are in [Key controls](https://5abeer.ai/en/docs/start/keys.md#controls).
- Keep `ALLOWED_CHAT_IDS` short unless the bot is meant to be public.
- If the bot token leaks, generate a new one with `/token` in BotFather. If the API key leaks, disable it and create a new one.

## FAQ

### Does Telegram charge for bot messages?

Not for normal messages. Telegram charges Stars only for paid broadcasts above the normal rate, so you pay for the model's tokens and the server.

### Can the bot use GPT or Gemini instead of Claude?

Yes. Set `BOT_MODEL` to a model id from the [models list](https://5abeer.ai/en/models) and use a key for that model's provider. Each key covers one provider, so a GPT model with a Claude key returns [`MODEL_PLATFORM_NOT_ALLOWED`](https://5abeer.ai/en/docs/help/errors.md#MODEL_PLATFORM_NOT_ALLOWED).

### Does the bot remember the conversation?

It remembers the last 10 messages of each chat while it runs. `/reset` clears that, and so does a restart. To keep memory across restarts, save `history` in a file or a database.

### Does it work in groups?

Yes, once the group's chat id is in `ALLOWED_CHAT_IDS`. By default, privacy mode is on: in a group the bot sees commands meant for it and replies to its own messages, not every message. A bot added as an admin sees all messages. To change privacy mode, use `/setprivacy` in BotFather, then remove the bot from the group and add it again. In a group, all members share one memory.

### What happens when my balance runs out?

Requests fail with [`INSUFFICIENT_BALANCE`](https://5abeer.ai/en/docs/help/errors.md#INSUFFICIENT_BALANCE), and the bot answers with its apology until you top up. It keeps running, so it answers again once the balance is back.

### How do I pay for the API?

You top up your 5abeer balance with any method in [Payment methods](https://5abeer.ai/en/docs/start/payment.md#methods), and the bot's API calls draw from that balance.

### Is 5abeer part of Telegram, OpenAI, Anthropic or Google?

No. 5abeer is an independent service, not affiliated with any of them.

## Sources

Checked on 2026-11-01:

- [Telegram Bot API](https://core.telegram.org/bots/api) (version 10.3): message length, `getUpdates`, `setWebhook`, file sizes
- [Telegram Bots FAQ](https://core.telegram.org/bots/faq): rate limits and broadcast cost
- [Telegram Bot Features](https://core.telegram.org/bots/features): BotFather, usernames, tokens and privacy mode

> 5abeer is an independent service, not affiliated with Telegram, OpenAI, Anthropic or Google.

## Get started

Create a Claude key, put it in `KHABEER_API_KEY` and start the bot.
