Most Telegram bots talk to api.telegram.org, and that is usually fine. File-heavy bots hit a wall, though: according to the official documentation, the standard Bot API lets a bot download files only up to 20 MB and upload only up to 50 MB. Telegram's answer is open source: run the Bot API server yourself.
What the local server gives you
The server code lives in the tdlib/telegram-bot-api repository. Started with --local, it allows:
- Downloading files without a size limit and uploading files up to 2000 MB.
- Uploading by local path using a
file://URI. getFilereturning an absolute local path instead of a download link.- Webhooks on any port and local IP, including plain HTTP.
Your bot still lives on the Telegram network; the local server only moves the middleman onto your machine, and users receive messages and files exactly as before. If your bot only handles text and small images, the standard API is simpler and you do not need any of this.
Example: a video studio bot
A small video studio in Fergana wants clients to send 300–800 MB wedding videos through a bot. With the standard API, getFile fails on such files. With a local server, files land directly on the server's disk. This needs a VPS, since shared hosting cannot compile and run your own long-lived service.
Credentials and build
Get api_id and api_hash at my.telegram.org under "API development tools", and treat them as secrets. Then build following the official instructions; compiling can take a lot of RAM, so add temporary swap on small servers.
sudo apt-get install -y make git zlib1g-dev libssl-dev gperf cmake g++
git clone --recursive https://github.com/tdlib/telegram-bot-api.git
cd telegram-bot-api
rm -rf build && mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local ..
cmake --build . --target install
Community Docker images exist and save build time, but they are unofficial, so check their source first.
Running it with systemd
# /etc/systemd/system/telegram-bot-api.service
[Unit]
Description=Telegram Bot API local server
After=network.target
[Service]
User=tgapi
EnvironmentFile=/etc/telegram-bot-api.env
ExecStart=/usr/local/bin/telegram-bot-api --local --http-port=8081 \
--http-ip-address=127.0.0.1 --dir=/var/lib/telegram-bot-api
Restart=always
[Install]
WantedBy=multi-user.target
Put TELEGRAM_API_ID and TELEGRAM_API_HASH in the env file, create the tgapi user and data directory, and run sudo systemctl enable --now telegram-bot-api. Never expose port 8081 publicly, or anyone who knows a bot token could route requests through your server. A quick sanity check is curl http://127.0.0.1:8081/bot<TOKEN>/getMe, which should return your bot's details once the server is up and the bot has been moved over.
Switching the bot over
Call logOut on the official server first. Per the docs, the bot then cannot reconnect to the official server for about 10 minutes, so plan the switch.
curl "https://api.telegram.org/bot<TOKEN>/logOut"
Then point your library at the local server. In aiogram 3:
session = AiohttpSession(
api=TelegramAPIServer.from_base("http://127.0.0.1:8081", is_local=True)
)
bot = Bot(token=TOKEN, session=session)
Disk space and maintenance
Downloaded files stay in the --dir directory and are never removed automatically, so schedule a cleanup job that moves processed files elsewhere and deletes old ones. Make sure the bot process has permission to read that directory, for example by sharing a group. Update the server from time to time, because new Bot API methods reach the local server only through new releases.