Local Telegram Bot API Server: When and How to Run Your Own
Advanced4 minInnovialabs editorial team
In short
A local Bot API server lets a bot upload files up to 2 GB, read downloaded files straight from disk and accept far more webhook connections; the price is that you build, update, secure and monitor it yourself.
What a local server gives you
By default a bot talks to Telegram through the cloud Bot API at api.telegram.org. That server is open source — telegram-bot-api from the TDLib team — and you can run it yourself. The bot then sends the same HTTP requests to your instance, and the instance talks to Telegram over MTProto.
Started with the --local flag, the server removes several cloud limits:
- Files up to 2000 MB can be uploaded, and files can be downloaded without the cloud size limit.
- Local file paths: you can send a file by its absolute path or a
file://URI, andgetFilereturns an absolute path on the server's disk instead of a download link. - Flexible webhooks: plain HTTP, any port, any local IP address and
max_webhook_connectionsup to 100000.
Your bot code barely changes — it is the same Bot API, only with a different base URL. The full list of differences is in the official Bot API documentation.
When it is worth it
- The bot handles video, archives, backups or large documents.
- Under heavy load you hit the webhook concurrency limit of the cloud API.
- The bot and the API server live in one private network, and you do not want a public HTTPS endpoint for webhooks.
For ordinary bots with text, buttons and small images, the cloud API is simpler and cheaper to maintain.
Building and running in Docker
You need an api_id and api_hash from my.telegram.org. They identify your application, not the bot, so treat them as secrets.
A multi-stage Dockerfile keeps the final image small. Note that compiling TDLib needs a lot of RAM — build on a machine with headroom or in CI.
FROM debian:bookworm-slim AS build
RUN apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates cmake g++ make gperf zlib1g-dev libssl-dev
RUN git clone --recursive https://github.com/tdlib/telegram-bot-api.git /src
WORKDIR /src/build
RUN cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/opt/tba .. \
&& cmake --build . --target install
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends zlib1g libssl3 ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=build /opt/tba/bin/telegram-bot-api /usr/local/bin/
EXPOSE 8081
ENTRYPOINT ["telegram-bot-api", "--local", "--dir=/var/lib/telegram-bot-api"]
The server reads TELEGRAM_API_ID and TELEGRAM_API_HASH from the environment, and listens on port 8081 by default:
docker build -t telegram-bot-api .
docker run -d --name tba --restart unless-stopped \
--env-file tba.env \
-v tba-data:/var/lib/telegram-bot-api \
-p 127.0.0.1:8081:8081 \
telegram-bot-api
Two details matter:
- Since
getFilereturns a path on the server's filesystem, the bot container must mount the same volume at the same path to read files. - Point the client library at the new base URL, for example in grammY:
new Bot(token, { client: { apiRoot: "http://tba:8081" } }). aiogram, python-telegram-bot and others have a similar setting.
Moving the bot: logOut and close
A bot must be logged out of the cloud server before it runs locally; otherwise update delivery is not guaranteed.
- Stop the bot process.
- Call
logOuton the cloud server:
curl "https://api.telegram.org/bot$BOT_TOKEN/logOut"
- Start the bot against your local server and, if you use webhooks, call
setWebhookagain — now through the local instance.
After logOut you can log in locally right away, but you cannot return to the cloud server for 10 minutes. Plan the switch so a rollback window of that length is acceptable.
To move a bot between two local servers, first call deleteWebhook, then close on the old instance. close returns error 429 during the first 10 minutes after the bot was launched.
Operational trade-offs
| Area | Cloud API | Your own server |
|---|---|---|
| Updates | New Bot API versions appear automatically | You rebuild and redeploy to get new methods |
| Disk | Not your concern | Files accumulate in the working directory and need cleanup |
| Security | HTTPS and isolation are provided | No TLS or auth on the HTTP port — keep it in a private network |
| Availability | Telegram's responsibility | Restarts, health checks, monitoring and alerts are on you |
| Secrets | Bot token only | Also api_id and api_hash |
The server accepts requests for any bot token, so an exposed port lets anyone use your infrastructure. Bind it to localhost or an internal network, and keep the working directory on a persistent volume.