In Telegram bot development, real-time responsiveness is key to delivering a good user experience. While long polling is a common method during initial development, webhooks are preferred for production due to their efficiency and real-time capabilities.
This guide walks through the steps to set up and test Telegram bot webhooks using Pinggy, a command-line tool that creates a secure public URL for your local server, simplifying webhook testing without needing external hosting.
What Are Telegram Bot Webhooks?
Telegram bots can receive updates using two methods:
- Long Polling: The bot periodically requests updates from Telegram.
- Webhooks: Telegram sends updates directly to a server endpoint you specify.
Webhooks offer several benefits over polling:
- Instant delivery of updates
- Reduced server load and bandwidth usage
- Better scalability for production environments
To use webhooks, your server must be publicly accessible over HTTPS, which can be a challenge during development. This is where tools like Pinggy are useful.
Step 1: Create a Telegram Bot
-
Start a chat and send
/newbot
-
Follow the prompts to set a name and username
You’ll receive a token that looks like
123456789:ABCDefGhIJKlmNoPQRsTUVwxyZ
Keep this token secure—it allows full control over your bot.
Step 2: Create a Local Webhook Server
Use Python and Flask to create a local server that receives JSON updates from Telegram.
from flask import Flask, request, jsonify
import logging
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
@app.route('/webhook', methods=['POST'])
def webhook():
update = request.get_json()
logging.info(f"Update received: {update}")
if 'message' in update:
chat_id = update['message']['chat']['id']
text = update['message'].get('text', '')
logging.info(f"Message from {chat_id}: {text}")
return jsonify({'status': 'ok'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
Install Flask:
pip install flask
Run the server:
python telegram_webhook.py
This creates a local server at http://localhost:8000/webhook
.
Step 3: Expose Your Local Server Using Pinggy
To allow Telegram to reach your local server, expose it via Pinggy.
Run the following command:
ssh -p 443 -R0:localhost:8000 [email protected]
Pinggy will provide a public HTTPS URL such as:
https://abcdefghij.a.pinggy.link
Step 4: Register the Webhook
Tell Telegram where to send updates using the Bot API:
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook" \
-d "url=https://abcdefghij.a.pinggy.link/webhook"
Replace <YOUR_BOT_TOKEN>
and the URL with your actual values. If successful, you should receive a confirmation response from Telegram.
Step 5: Test the Webhook
- Open Telegram and send a message to your bot.
- Check the terminal where your Flask server is running.
- You should see log entries showing the update payload and message content.
Example log:
INFO:root:Update received: {...}
INFO:root:Message from 123456789: Hello
Enhancing Your Webhook Server
To respond to messages, extend the server with message-sending capabilities.
import requests
def send_message(chat_id, text, token):
url = f"https://api.telegram.org/bot{token}/sendMessage"
payload = {"chat_id": chat_id, "text": text}
response = requests.post(url, json=payload)
return response.json()
You can integrate this function into the webhook handler to send replies based on user messages.
Conclusion
Webhooks provide a reliable and efficient mechanism for real-time bot communication. For developers testing on local machines, Pinggy offers a practical solution to expose local webhook endpoints securely and temporarily. This setup allows thorough testing before deploying to production environments.
Top comments (2)
That Pinggy trick for quick webhook testing is a real time saver, thanks for laying it out so clearly. Have you ever tried using tools like ngrok for this, or do you find Pinggy consistently smoother?
Yeah, I’ve used ngrok before, it is good. But honestly, I find Pinggy a lot easier to set up and use. It just feels smoother in my experience. One thing I like is that it supports UDP tunnels—that's been super handy for a few things I’ve worked on. Also, the $3/month price point was a nice surprise—pretty affordable for what it offers.