API

Build a Telegram Bot That Removes Image Backgrounds (python-telegram-bot + API)

September 6, 20266 min readBy BG Clear Editorial

Telegram bots are the quickest way to put a background remover in front of people who will never visit a website — WhatsApp-first sellers, students, small teams. The whole bot is one Python file: python-telegram-bot handles the messaging, an HTTP call does the removal, and long polling means it runs from any laptop or $5 VPS without a public URL. This guide builds it with the bgclear API, keeps previews free, and charges credits only when a user asks for HD.

In this guide

Setup

Create the bot with @BotFather in Telegram and copy the token. Get a bgclear key from the API dashboard (10 free full-resolution credits; preview-size results are free without limit).

pip install "python-telegram-bot>=20" httpx
export TELEGRAM_BOT_TOKEN=123456:ABC...
export BGCLEAR_API_KEY=bgc_live_...

The bot

Two Telegram details shape the code. Photos sent as photos are recompressed to JPEG by Telegram, so the bot accepts both photos and image documents, and it always replies with a document — that is the only way the transparent PNG survives. And the largest photo size is the last element of message.photo.

import os, time, logging
import httpx
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, ContextTypes, filters

API = "https://www.bgclear.ai/api/v1/remove"
KEY = os.environ["BGCLEAR_API_KEY"]
COOLDOWN = 10          # seconds between requests per user
last_seen: dict[int, float] = {}
logging.basicConfig(level=logging.INFO)

async def remove_background(data: bytes, size: str) -> tuple[bytes | None, str]:
    async with httpx.AsyncClient(timeout=90) as client:
        r = await client.post(
            API,
            headers={"Authorization": f"Bearer {KEY}"},
            files={"image_file": ("photo.jpg", data, "image/jpeg")},
            data={"size": size, "format": "png"},
        )
    if r.status_code == 200:
        return r.content, r.headers.get("X-Credits-Remaining", "?")
    err = r.json().get("error", {})
    return None, f"{r.status_code} {err.get('code')}: {err.get('message')}"

async def handle_image(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    msg = update.message
    now = time.time()
    if now - last_seen.get(msg.from_user.id, 0) < COOLDOWN:
        await msg.reply_text("Easy — one image every 10 seconds.")
        return
    last_seen[msg.from_user.id] = now

    tg_file = await (msg.document or msg.photo[-1]).get_file()   # document keeps full quality
    data = bytes(await tg_file.download_as_bytearray())
    size = "full" if context.user_data.get("hd") else "preview"   # preview is free

    await msg.reply_chat_action("upload_document")
    png, info = await remove_background(data, size)
    if png is None:
        await msg.reply_text(f"Could not process that image ({info}).")
        return
    await msg.reply_document(document=png, filename="cutout.png",
                             caption=f"Background removed ({size}). Send /hd for full resolution.")
    context.user_data["hd"] = False                               # HD is per request

async def hd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    context.user_data["hd"] = True
    await update.message.reply_text("Next image will be processed at full resolution (1 credit).")

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("Send me a photo and I will remove the background. "
                                    "Send it as a file for best quality. /hd before an image for full resolution.")

app = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("hd", hd))
app.add_handler(MessageHandler(filters.PHOTO | filters.Document.IMAGE, handle_image))
app.run_polling()

Run it with python bot.py. Long polling pulls updates from Telegram, so the bot works behind NAT, on a laptop, or in a container with no inbound port.

Keeping it cheap and abuse-proof

Previews (≤800 px) are free at the API, so the default path costs nothing no matter how many people use the bot. /hd spends one credit — gate it behind an allow-list of user ids, a Telegram Stars payment, or a daily quota per user if the bot is public. The per-user cooldown above is in memory; a Redis counter keyed by user id survives restarts. Rate limit at the API is 60 requests a minute per key; if the bot grows past that, queue requests with a semaphore of 4–5 concurrent calls.

Telegram's own limits: bots can download files up to 20 MB, and image documents over about 10 MB are best downscaled before sending to the API. Log X-Credits-Remaining (returned with every response) and alert yourself below a threshold so the bot never dies with a 402 in front of users.

Deploying and cost

Any always-on Python host works — a small VPS, Fly.io, Railway, a Raspberry Pi — because polling needs no public URL. Store the two tokens as environment variables, never in the file. API cost is one credit per HD image: $9 for 100, $39 for 500, $129 for 2,000, no subscription, previews free, failed requests never charged (pricing). The same handler shape works for a Discord bot; for WhatsApp-style use cases in India, the Hindi WhatsApp DP guide covers the web tool.

Frequently asked questions

Why does the bot reply with a file instead of a photo?

Telegram converts photos to JPEG, which cannot hold transparency. Sending the PNG as a document preserves the transparent background.

Do I need a server with a public URL?

No — the bot uses long polling, so it runs anywhere with outbound internet. Webhooks are optional and only matter at very high volume.

Can users send images as files?

Yes, and they should for best quality: the handler accepts both photos and image documents.

What does each image cost?

Previews are free. Full-resolution (/hd) images are one credit — $0.065 to $0.09 depending on pack, credits never expire.

Ship it with the bgclear API

remove.bg-compatible endpoints, credits from $9 for 100 images, no subscription. Pay, get a key, make your first call in under two minutes.

Get API credits →

Tools for this guide

Background Removal API Free

background removal api free

Background Remover Python Library

background remover python library

Cheapest Background Remover API

cheapest background remover api

Keep reading

API

Build a Discord Bot That Removes Image Backgrounds (discord.js, 80 Lines)

A /cutout slash command that takes an attachment, sends it through a background removal API and replies with the transparent PNG — with deferred replies, a per-user cooldown, and free previews so the bot costs nothing until someone asks for HD.

API

Remove Image Backgrounds in Python with an API (requests, 20 Lines)

A complete Python walkthrough: single image, URL input, JSON responses, a folder script with safe retries, and async jobs for large files — no ML libraries, just requests.

API

Django and FastAPI: a Background Removal Proxy Endpoint That Keeps Your API Key Safe

A FastAPI endpoint with httpx that streams the cutout back, the Django view equivalent, per-user quotas, and a Celery task for catalogue runs — the pattern behind every web or mobile front end that removes backgrounds.

API

A Free Background Removal API for GitHub Projects: What Is Actually Free, Plus a GitHub Action

The honest free tier (unlimited previews, 10 credits, a free RapidAPI plan), how to keep the key out of a public repo, and a GitHub Actions workflow that removes backgrounds from images in CI — free in pull requests, paid only on release.