Skip to content

Instantly share code, notes, and snippets.

@turicas
Created December 2, 2025 19:28
Show Gist options
  • Select an option

  • Save turicas/04c8d673e04b2149143d5fc5b60721c5 to your computer and use it in GitHub Desktop.

Select an option

Save turicas/04c8d673e04b2149143d5fc5b60721c5 to your computer and use it in GitHub Desktop.
CLI to send messages via Telegram API Bot (using only Python stdlib)
import argparse
import os
import sys
from http.client import HTTPResponse
from urllib.error import HTTPError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
def send_telegram_message(token: str, chat_id: int, message: str, parse_mode: str, timeout: float) -> HTTPResponse:
"Send a message as a bot using the Telegram Bot API"
api_url = f"https://api.telegram.org/bot{token}/sendMessage"
payload = {"chat_id": chat_id, "text": message, "parse_mode": parse_mode}
encoded_data = urlencode(payload).encode()
request = Request(api_url, data=encoded_data, method="POST")
response = urlopen(request, timeout=timeout)
return response
def cli_parser() -> argparse.ArgumentParser:
"Create the CLI parser object"
parse_mode_choices = ("Markdown", "MarkdownV2", "HTML")
parser = argparse.ArgumentParser(description="Send messages as a Telegram Bot to a group/person")
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Show response JSON",
)
parser.add_argument(
"-t",
"--token",
help="Bot token (also read from TELEGRAM_BOT_TOKEN env var)",
default=os.environ.get("TELEGRAM_BOT_TOKEN"),
)
parser.add_argument("-T", "--timeout", type=float, default=10.0)
parser.add_argument(
"-m",
"--parse-mode",
help="How Telegram should parse the message contents. Options: {', '.join(choices)}",
default="Markdownv2",
choices=parse_mode_choices,
)
parser.add_argument("chat_id")
parser.add_argument("message")
return parser
def print_response(response: HTTPResponse) -> None:
"Print the response from Telegram Bot API to stderr"
import json
from textwrap import indent
json_data = response.read()
error = response.status != 200
if error:
print(f"ERROR: response status code: {response.status} ({response.msg})", file=sys.stderr)
print(" Headers:")
for key, value in response.headers.items():
print(f" - {key:40}: {value}")
print(" Content:", file=sys.stderr)
try:
data = json.loads(json_data)
except json.JSONDecodeError:
print(json_data, file=sys.stderr)
else:
content = json.dumps(data, indent=2)
if error:
content = indent(content, " ")
print(content, file=sys.stderr)
def main():
parser = cli_parser()
args = parser.parse_args()
if args.token is None:
print("ERROR: the bot token must be specified either via TELEGRAM_BOT_TOKEN or --token", file=sys.stderr)
sys.exit(1)
try:
response = send_telegram_message(
token=args.token,
chat_id=args.chat_id,
message=args.message,
parse_mode=args.parse_mode,
timeout=args.timeout,
)
except HTTPError as exception:
print_response(exception.fp)
else:
if args.verbose:
print_response(response)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment