How2Code/Automations/Website form → Telegram

REAL BUILD · AUTOMATION

How to Send Website Form Submissions to Telegram

Build a secure contact form that sends new website leads straight to Telegram — without exposing your bot token in the browser.

DIFFICULTYBeginner+TIME~30 minSTACKHTML · Django · Telegram APIRESULTWorking contact form
Website formName · Email · Message
→
Secure backendValidate · protect · format
→
Telegram Bot APIsendMessage
→
New website leadDelivered to Telegram

Send a test lead

This form uses the same architecture you'll build below. Your browser sends the form to How2Code's Django backend; the backend sends the Telegram message. The bot token never reaches the page.

Ready to send
✦Telegram

New How2Code demo submission

Name: John Smith
Email: [email protected]
Message: I'd like a quote

SECURITY

The demo destination is fixed on the server. Visitors cannot provide a bot token, chat ID or arbitrary destination, so this endpoint cannot act as a general-purpose Telegram relay.

Describe the form you actually need

Don't copy our contact form field for field. Tell How2Code what your business or workflow needs. AI will adapt this proven Website Form → Django → Telegram pattern and give you the files and setup steps.

3 free builds per hour

A small form with a server in the middle

The browser should not talk directly to Telegram with your bot token. Instead, it sends ordinary form data to an endpoint you control. That endpoint validates the submission and makes the authenticated Telegram request.

Browserknows/contact/ServerknowsBOT_TOKEN + CHAT_ID

We're using Django because How2Code runs on Django, but the same boundary works with Flask, FastAPI, Node, PHP, Laravel or a serverless function.

Before you start

  • A Telegram account
  • A website with a backend you control
  • Python and Django for this implementation
  • A place to store environment variables in production

STEP 1

Create a Telegram bot

Open @BotFather in Telegram, start a chat and run /newbot. Choose a display name and username. BotFather will return an authentication token.

KEEP THE TOKEN PRIVATE

A bot token authenticates API requests as your bot. Do not paste it into HTML, browser JavaScript, screenshots or a public Git repository.

STEP 2

Get the destination chat ID

Send a message to your new bot first. Then call Telegram's getUpdates method from a trusted environment and inspect the returned message object's chat.id.

Terminal / browser on your machine
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates

For a group, add the bot to the group and send a message there. Group and supergroup IDs can be negative. Keep the chat ID server-side too: it isn't an authentication secret like the token, but clients do not need it.

STEP 3

Create the website form

Start with normal HTML. This keeps the form usable and understandable before we add any JavaScript enhancement.

contact.html
<form method="post" action="/contact/">
  {% csrf_token %}
  <label>Name
    <input name="name" maxlength="80" required>
  </label>
  <label>Email
    <input type="email" name="email" required>
  </label>
  <label>Message
    <textarea name="message" maxlength="1000" required></textarea>
  </label>
  <button type="submit">Send</button>
</form>

STEP 4

Create the secure backend endpoint

Django validates the fields before Telegram sees anything. The hidden honeypot is deliberately boring: many automated form bots fill every input they find.

forms.py
from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=80, strip=True)
    email = forms.EmailField(max_length=254)
    message = forms.CharField(max_length=1000, strip=True)
    website = forms.CharField(required=False)

    def clean_website(self):
        if self.cleaned_data.get("website"):
            raise forms.ValidationError("Invalid submission.")
        return ""
views.py
from django.shortcuts import render
from django.views.decorators.http import require_POST

@require_POST
def contact(request):
    form = ContactForm(request.POST)
    if not form.is_valid():
        return render(request, "contact.html", {"form": form}, status=400)

    send_to_telegram(
        name=form.cleaned_data["name"],
        email=form.cleaned_data["email"],
        message=form.cleaned_data["message"],
    )
    return render(request, "contact_success.html")

STEP 5

Send the message through Telegram Bot API

The authenticated request happens here, on the server. A short timeout matters: if Telegram is temporarily unreachable, your web worker should not hang indefinitely.

telegram.py
import json
import os
from urllib import request

def send_to_telegram(*, name, email, message):
    token = os.environ["TELEGRAM_BOT_TOKEN"]
    chat_id = os.environ["TELEGRAM_CHAT_ID"]

    text = (
        "New website lead\n\n"
        f"Name: {name}\n"
        f"Email: {email}\n"
        f"Message: {message}"
    )
    payload = json.dumps({
        "chat_id": chat_id,
        "text": text,
    }).encode("utf-8")

    req = request.Request(
        f"https://api.telegram.org/bot{token}/sendMessage",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with request.urlopen(req, timeout=5):
        pass
WHY NO TELEGRAM PACKAGE?

For one sendMessage call, Python's standard library keeps the example small and exposes the actual HTTP boundary. A bot framework makes sense when your application starts receiving commands, callbacks and updates.

STEP 6

Store secrets outside the code

Set the token and destination as environment variables on the machine or hosting platform running Django.

Environment
TELEGRAM_BOT_TOKEN=123456:replace-with-real-token
TELEGRAM_CHAT_ID=123456789

Add local environment files to .gitignore. Never commit the real token. If a token has been exposed, revoke/regenerate it with BotFather rather than merely deleting it from the latest commit.

STEP 7

Make the public endpoint boring to abuse

A production form needs more than a hidden token. Our live demo uses server-side validation, Django CSRF protection, a honeypot, strict length limits, a fixed Telegram destination and request throttling.

CSRF

Reject forged browser submissions.

Validation

Accept only the fields and sizes you expect.

Honeypot

Drop simple automated form fillers.

Rate limit

Cap repeated submissions per source.

Fixed target

Never accept a chat ID from the visitor.

Safe errors

Don't leak Telegram responses or secrets.

STEP 8

Test the failure cases, not only the happy path

  • A valid submission reaches Telegram
  • Empty name/message is rejected
  • An invalid email is rejected
  • The bot token is absent from page source and JavaScript
  • Repeated submissions are throttled
  • A Telegram outage produces a safe user-facing error

STEP 9

Deploy it

The deployment rule is simple: configure the two environment variables where your Django process starts, restart the application, then submit the production form once and verify the message arrives.

systemd example
[Service]
Environment="TELEGRAM_BOT_TOKEN=..."
Environment="TELEGRAM_CHAT_ID=..."
ExecStart=/path/to/venv/bin/gunicorn config.wsgi:application
DON'T COPY YOUR REAL TOKEN INTO A TUTORIAL COMMAND

Use your host's secret/environment mechanism when available. The exact configuration differs between systemd, Docker, Render, Railway, Fly.io and other platforms.

What we asked AI — and what still needed engineering

PROMPT

Build a Django contact form with name, email and message fields. When submitted, send the data to a Telegram bot. Keep the implementation simple.

A first AI answer can be working and still be unfinished

Typical first draftWhat we ship instead
Token copied into sourceEnvironment variable
Raw POST valuesDjango form validation
No abuse protectionCSRF + honeypot + throttling
No network timeoutBounded Telegram request
Telegram error shown directlySafe application error

AI gets you from zero → working.
Engineering gets you from working → shippable.

Keep the pieces small

The production pattern is only four responsibilities: HTML collects the data, a Django form validates it, a view controls the request, and a tiny Telegram client owns the external API call. That separation makes each part easy to replace later.

templates/contact.htmlform UIforms.pyvalidationviews.pyrequest + responsetelegram.pyTelegram API

When the form doesn't reach Telegram

The API returns 401 Unauthorized

The bot token is invalid or has been revoked. Get the current token from BotFather and update the server environment.

The API returns “chat not found”

Check the chat ID and make sure the bot has access to that chat. For a private chat, message the bot first. For a group, add the bot and generate an update from that group.

getUpdates returns nothing

Send the bot a new message and try again. If the bot is configured to receive updates through a webhook, getUpdates cannot be used at the same time.

The form works locally but fails in production

Check that the production process actually receives the environment variables, can make outbound HTTPS requests, and was restarted after configuration changed.

Django returns CSRF verification failed

Render the CSRF token inside the form and submit to the same Django site. Don't disable CSRF just to make the error disappear.

Where to take it next

Once the basic path is reliable, you can store leads in your database, send an email fallback, attach page/UTM data, push the same lead into a CRM, or route different forms to different internal chats. Add those because your workflow needs them — not because the first version needs more code.

Common questions

Can I send an HTML form directly to Telegram?

Technically a browser can call the Bot API, but doing so exposes the bot token to every visitor. Use a backend or serverless endpoint between the form and Telegram.

Do I need a Telegram webhook for a contact form?

No. A webhook is for Telegram sending updates to your application. Here your application is making an outbound sendMessage request to Telegram.

Can I use this without Django?

Yes. The important architecture is browser → your trusted server endpoint → Telegram Bot API. The middle layer can be implemented in Node, PHP, Flask, FastAPI, Laravel or a serverless function.

Is the Telegram chat ID secret?

The bot token is the authentication secret. The chat ID is not equivalent to a password, but there is no reason to expose it to the browser in this architecture.

Build it yourself.
Or connect your real workflow.

Need this connected to your existing website, CRM, email, Telegram or WhatsApp? How2Code can build the production version around the tools you already use.

Tell us what you need →