// DevOps
Local Telegram Bot API Server in Docker: 2 GB File Limit
Published on 2026-09-22
Local Telegram Bot API allows developers to run their own API server, providing significant advantages for working with large files, performance, and configuration flexibility. However, to understand the need for a local server it’s important to consider the limitations of the standard Telegram Bot API that works over HTTPS. In this article we will review the advantages of the Local Bot API, limitations of the standard approach, and steps to set up a local server via Docker, including registering a bot to use it.
🚀 Key advantages of the Local Bot API
1. Increased file handling limits
For developers whose bots actively work with media, a local API server opens new possibilities:
Upload files up to 2 GB:
Unlike the standard Bot API, which limits upload size to 50 MB, the local server allows working with files up to 2000 MB (2 GB). This is ideal for bots that process video, audio, or other large media files.Download files without strict limits:
The local API allows downloading files from Telegram servers without strict size limits (up to 2000 MB), while the standard API restricts downloads to 20 MB.Use local path for uploads:
The local API server supports specifying a local path or thefile://URI scheme for uploads, eliminating the need to transmit files via HTTP requests.
2. Reduced network latency
A local API server can significantly improve performance:
- Latency reduction:
Requests from your bot are first sent to your local API server and then forwarded to Telegram servers.
If your bot and API server are in the same network or geographically close, this can reduce network latency, providing faster request handling.
3. Flexibility and increased webhook limits
Using a local API server expands webhook configuration options:
HTTP support:
Unlike the standard Bot API, which requires HTTPS, the local server allows using HTTP for webhooks, which simplifies setup in some scenarios.Any IP and port:
You can configure webhooks on any local IP address and any port, providing flexibility in server configuration.More concurrent connections:
Themax_webhook_connectionsparameter on the local server can be raised up to 100,000 (default in--localmode is 100). The standard API allows values from 1 to 100, default 40, and webhooks are accepted only over HTTPS on ports 443, 80, 88 or 8443.
4. Faster file access
In --local mode the getFile method returns an absolute local path to the file (file_path) and does not require a separate download. For the bot to read such a file it must have access to the server’s data directory — for example, a shared Docker volume.
All advantages in this section work only when the server is started with the --local flag. Without it the local server behaves like the cloud: same file limits and the same webhook requirements.
🛑 Limitations of the standard Telegram Bot API
| Parameter | Limit | Note |
|---|---|---|
| Global limit | ≤ 30 messages per second | Maximum sending rate from one bot across all chats. |
| Single chat (private) | ≤ 1 message per second | Per user. |
| Group/channel | ≤ 20 messages per minute | Per chat. |
| File upload | ≤ 50 MB | Via the standard API. |
| File download | ≤ 20 MB | When downloading from Telegram servers. |
| Message length | ≤ 4096 characters | — |
| Media caption | ≤ 1024 characters | — |
| Inline buttons | ≤ 100 | — |
| Commands | ≤ 100 | Configured via @BotFather. |
| Webhooks | HTTPS only and limited ports | 443, 80, 88, 8443 |
🛠 Setting up Local Bot API with Docker
1. Preparation
Before starting, make sure you have Docker and Docker Compose installed, and that you have your API ID and API Hash obtained from my.telegram.org.
Create a .env file:
TELEGRAM_API_ID=your_api_id
TELEGRAM_API_HASH=your_api_hash2. Docker Compose configuration
docker-compose.yml file:
services:
telegram-bot-api:
build: ./telegram-bot-api-builder
container_name: telegram-local-api
restart: unless-stopped
environment:
TELEGRAM_API_ID: ${TELEGRAM_API_ID}
TELEGRAM_API_HASH: ${TELEGRAM_API_HASH}
ports:
- "127.0.0.1:8081:8081"
volumes:
- tgdata:/var/lib/telegram-bot-api
command:
- --local
- --http-port=8081
- --dir=/var/lib/telegram-bot-api
- --temp-dir=/tmp/telegram-bot-api
volumes:
tgdata:What’s important in this configuration:
--localenables local mode: files up to 2000 MB, webhooks over HTTP on any port, local paths ingetFile. Without this flag the server runs with the same limits as the cloud.- The server reads
TELEGRAM_API_IDandTELEGRAM_API_HASHfrom environment variables, so you don’t need to pass them additionally as--api-idand--api-hasharguments. - Port is published only on
127.0.0.1. The server accepts requests using a single bot token without other checks, so do not expose it to the internet. If the bot runs in the same Compose project, it can contact the server by service namehttp://telegram-bot-api:8081, and you don’t need to publish the port at all. - The
version:line at the start of the file is deprecated: modern Docker Compose ignores it and emits a warning.
3. Dockerfile
telegram-bot-api-builder/Dockerfile:
# ---------- Stage 1: Build ----------
FROM ubuntu:24.04 AS builder
ARG DEBIAN_FRONTEND=noninteractive
# Branch or commit to build; for reproducibility specify the commit hash:
# --build-arg TELEGRAM_BOT_API_REF=<commit>
ARG TELEGRAM_BOT_API_REF=master
# Build dependencies from the official instructions (gperf is required)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
make git zlib1g-dev libssl-dev gperf cmake g++ ca-certificates && \
rm -rf /var/lib/apt/lists/*
# Repository is cloned recursively: TDLib is included as a submodule
WORKDIR /src
RUN git clone --recursive https://github.com/tdlib/telegram-bot-api.git . && \
git checkout "${TELEGRAM_BOT_API_REF}" && \
git submodule update --init --recursive
# Build
RUN mkdir -p build && cd build && \
cmake -DCMAKE_BUILD_TYPE=Release .. && \
cmake --build . --target telegram-bot-api -j"$(nproc)"
# Strip the binary (reduce size)
RUN strip /src/build/telegram-bot-api || true
# ---------- Stage 2: Runtime ----------
FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
# Minimal runtime dependencies:
# in Ubuntu 24.04 the OpenSSL library is called libssl3t64
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libssl3t64 zlib1g ca-certificates && \
rm -rf /var/lib/apt/lists/*
# Data directory + system user
RUN groupadd -r telegram-bot-api && \
useradd -r -g telegram-bot-api -d /var/lib/telegram-bot-api -s /sbin/nologin telegram-bot-api && \
mkdir -p /var/lib/telegram-bot-api /tmp/telegram-bot-api && \
chown -R telegram-bot-api:telegram-bot-api /var/lib/telegram-bot-api /tmp/telegram-bot-api
# Copy the binary
COPY --from=builder /src/build/telegram-bot-api /usr/local/bin/telegram-bot-api
# Default port (change in docker-compose with --http-port)
EXPOSE 8081
# Healthcheck: verify that the server accepts TCP connections on the port
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD bash -c 'exec 3<>/dev/tcp/127.0.0.1/8081' || exit 1
USER telegram-bot-api
WORKDIR /var/lib/telegram-bot-api
# Parameters are passed via docker-compose (command), API keys via environment variables
ENTRYPOINT ["/usr/local/bin/telegram-bot-api"]Features of this variant:
- Dependencies and
git clone --recursivefollow the official build instructions. Withoutgperfand without the TDLib submodule the build will fail. - Base image — Ubuntu 24.04; runtime requires the
libssl3t64package. - Parallel build and
stripthe binary to reduce size. HEALTHCHECKverifies that the port accepts connections. Checking withcurl -fon the root URL is not suitable here: the server responds to such a request with an error.- The server runs as a non-privileged user.
- The
TELEGRAM_BOT_API_REFargument allows pinning the build to a specific commit.
4. Starting the server
docker compose up -d --buildAfter starting, the server will be accessible at:
http://localhost:80815. Checking and registering the bot
If the bot previously worked via the cloud API, before switching to a local server you must disconnect it from the cloud using the logOut method. Otherwise some updates may continue to be sent to Telegram’s servers:
curl https://api.telegram.org/bot<YOUR_TOKEN>/logOutAfter a successful call you can only return the bot to the cloud after 10 minutes. To move a bot from one local server to another, call deleteWebhook and close on the old server.
Then check the local server:
curl http://localhost:8081/bot<YOUR_TOKEN>/getMeIf you see a JSON response with the bot’s name — everything works.
6. Usage in code
Python (python-telegram-bot 20 and newer)
from telegram.ext import ApplicationBuilder
application = (
ApplicationBuilder()
.token("YOUR_TOKEN")
.base_url("http://localhost:8081/bot")
.base_file_url("http://localhost:8081/file/bot")
.local_mode(True)
.build()
)The address should include the /bot suffix: by default the library targets https://api.telegram.org/bot. The class Updater(token, base_url=...) from older examples belongs to version 13 and does not work in current versions. local_mode(True) is required when the server is started with --local: then get_file() returns a local path and the library does not try to download the file.
Any other language or library
Bot API is a regular HTTP interface: just replace https://api.telegram.org in your client with your server address. The parameter name depends on the library — look for base URL or API URL in its documentation. You can test operation without a library:
curl -X POST "http://localhost:8081/bot<YOUR_TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id": 123456789, "text": "Local server test"}'7. Configuring Webhook
curl -X POST "http://localhost:8081/bot<YOUR_TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url": "http://bot:8443/telegram-webhook"}'The url should point to your bot — the application that receives updates, not the Bot API server address. In the example the bot runs in the same Compose project as the bot service and listens on port 8443. In --local mode the webhook can be HTTP, on any port, and on a local address.
8. HTTPS and HTTP version error
The Bot API server accepts only HTTP requests. If you need to access it from outside over HTTPS, place a TLS proxy in front of it — nginx, Caddy, or HAProxy.
The server understands only HTTP/1.0 and HTTP/1.1. For requests using a different protocol version it responds with 505 HTTP Version Not Supported, and client libraries convert this into messages like “self hosted bot api instances only support HTTP/1.1”. The reasons are usually twofold:
- Client is configured for HTTP/2. In
python-telegram-botthis is thehttp_version="2"parameter for requests; the default"1.1"is sufficient — don’t change it. In other libraries disable HTTP/2 for the local server address. - Proxy communicates with the server using HTTP/2. Between the proxy and the Bot API server it must be HTTP/1.1. In nginx set
proxy_http_version 1.1;inside thelocationblock; you can keep HTTP/2 on the client side.
💡 Summary
Local Telegram Bot API is suitable for:
- working with large files (up to 2 GB);
- reducing latency;
- flexible webhook configuration;
- high-load systems.
The standard API is suitable for:
- small projects;
- working with files up to 50 MB;
- typical HTTPS webhooks.
Building in Docker gives a reproducible image and simple updates. The main points when switching are: start the server with --local, call logOut for the cloud API, and do not publish the server port to the internet.
🔗 Useful links
Frequently Asked Questions
What is the local Telegram Bot API server?
What is the maximum file size supported by the local Telegram Bot API?
Does the local Telegram Bot API require HTTPS?
How do I run the local Telegram Bot API server with Docker?
What is the difference between the standard and local Telegram Bot API?
How many concurrent connections does the local Telegram Bot API support?
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related