To notify a manager when a website visitor submits a form, have the form post to a PHP handler and let that server-side handler call Telegram’s Bot API sendMessage method. Keep the bot token on the server, make sure the recipient has started the bot or add it to a team group, validate the submitted fields, and report success only after Telegram returns ok: true.
How the form-to-Telegram flow works
- A visitor submits an ordinary HTML form to a PHP endpoint.
- The PHP endpoint validates and normalizes the submitted values.
- PHP sends an HTTPS POST to Telegram’s
sendMessagemethod with a destinationchat_idand messagetext. - The handler checks both the HTTP client result and Telegram’s JSON response before showing a success message.
Telegram describes its Bot API as an HTTP-based interface for building Telegram bots. Its request URL follows the form https://api.telegram.org/bot<token>/METHOD_NAME; for this workflow, the method is sendMessage. The API accepts POST data as JSON or URL-encoded form data, among other supported formats. See Telegram’s Bot API reference.
As an Amazon Associate I earn from qualifying purchases.
Choose where notifications should go
| Destination | What to configure | Trade-off |
|---|---|---|
| Private chat with a manager | Each manager must first message the bot, for example by sending /start, and you need that manager’s chat_id. |
Notifications can be directed to an individual, but each recipient must initiate contact with the bot. Telegram says bots cannot start private conversations with users. See Telegram’s bot introduction and Bot API reference. |
| Team group | Add the bot to the group, confirm it can post, and configure the group’s chat identifier. | One destination can notify several managers. Telegram’s group message limits apply. See Telegram’s bot FAQ. |
The Bot API accepts an integer chat ID or, where supported, a chat username. For a private group, configure its actual identifier rather than assuming a username will work.
Create the bot and protect its token
- In Telegram, use
@BotFatherto create a bot and obtain its token. - Store the token in a server-side environment variable or protected configuration. Do not put it in browser JavaScript, HTML, a public repository, or a URL rendered to visitors.
- Configure the destination chat ID in the same server-side configuration.
The token is a credential: Telegram warns, “Everyone who has your token will have full control over your bot.” If it is exposed, revoke or regenerate it through BotFather and update the server configuration. Details are in Telegram’s bot introduction.
#1 Best Overall
Build the PHP handler
The following example expects an HTML form with name, email, and message fields posting to this PHP file. Set the TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID environment variables on the server, and ensure PHP’s cURL extension is enabled.
<?php
// form-handler.php
function fail(int $status, string $message): never
{
http_response_code($status);
echo htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
fail(405, 'Submit this endpoint using the form.');
}
$name = $_POST['name'] ?? null;
$email = $_POST['email'] ?? null;
$message = $_POST['message'] ?? null;
if (!is_string($name) || !is_string($email) || !is_string($message)) {
fail(400, 'Please provide valid form fields.');
}
$name = trim($name);
$email = trim($email);
$message = trim($message);
if ($name === '' || strlen($name) > 120 ||
$email === '' || strlen($email) > 254 || !filter_var($email, FILTER_VALIDATE_EMAIL) ||
$message === '' || strlen($message) > 3000) {
fail(400, 'Check the name, email address, and message, then try again.');
}
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = getenv('TELEGRAM_CHAT_ID');
if (!$token || !$chatId) {
error_log('Telegram form handler is missing server configuration.');
fail(500, 'The form could not be sent. Please try again later.');
}
$text = "New website form submissionn" .
"Name: {$name}n" .
"Email: {$email}n" .
"Message:n{$message}";
$payload = json_encode([
'chat_id' => $chatId,
'text' => $text,
], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
if ($payload === false) {
fail(400, 'The message could not be processed. Please check the form and try again.');
}
$ch = curl_init("https://api.telegram.org/bot{$token}/sendMessage");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 10,
]);
$responseBody = curl_exec($ch);
$curlError = curl_error($ch);
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($responseBody === false) {
error_log('Telegram request transport failed: ' . $curlError);
fail(502, 'We could not send your message. Please try again later.');
}
$result = json_decode($responseBody, true);
if (!is_array($result) || ($result['ok'] ?? false) !== true) {
$description = is_array($result) ? ($result['description'] ?? 'Unknown Telegram API error') : 'Invalid API response';
error_log('Telegram API rejected form notification (HTTP ' . $httpStatus . '): ' . $description);
fail(502, 'We could not send your message. Please try again later.');
}
echo 'Thank you. Your message has been sent.';
Match the handler to your form
Use a standard POST form and set its action to the handler’s URL. For example:
Rank #2
<form method="post" action="/form-handler.php">
<label>Name <input name="name" required maxlength="120"></label>
<label>Email <input name="email" type="email" required maxlength="254"></label>
<label>Message <textarea name="message" required maxlength="3000"></textarea></label>
<button type="submit">Send</button>
</form>
PHP makes standard form-encoded submissions available in $_POST. The server-side checks remain necessary even when the browser form uses required, maxlength, or an email input type; visitors can bypass client-side constraints.
Recommended Free Tools
Why validate and escape separately
Check that values are strings, required values are present, and lengths are appropriate for your form. PHP’s default filter_input filter does not filter input by itself. Validation checks whether a value fits your expectations; escaping is specific to where a value is later displayed. The example escapes the plain-text browser response with htmlspecialchars. If you later render submitted values in an HTML page, escape them for that HTML context as well. For Telegram, this example sends plain text without a parse mode, avoiding Markdown or HTML entity rules. See PHP’s filter_input documentation and PHP’s htmlspecialchars documentation.
Verify delivery and handle failures safely
There are two different failure points. A cURL transport error means PHP did not successfully complete the HTTP request. If cURL returns a response body, Telegram may still reject the request; decode the JSON and require ok: true. Telegram responses can include a human-readable description when a call fails. Do not treat a successful cURL call alone as proof that the notification was sent.
- Keep connection and overall request timeouts so a slow service does not leave the form request hanging indefinitely.
- Log a safe diagnostic on the server, but do not return the bot token, raw API URL, submitted message, or internal error details to the visitor.
- Show a success confirmation only after Telegram accepts the message. If sending fails, give the visitor a retry or support route rather than a false confirmation.
- Check your server’s PHP error log and verify the token, chat ID, recipient setup, and cURL extension when troubleshooting.
PHP documents cURL request setup, response capture, POST bodies, and transfer-error checks in its basic cURL examples. Telegram also publishes a PHP Bot API sample that uses cURL and timeouts.
Rank #4
Control spam, duplicates, and rate limits
A public form can be submitted repeatedly, intentionally or accidentally. Add proportionate controls such as server-side validation, a honeypot or challenge when appropriate, request throttling, and duplicate-submit protection. Avoid automatically retrying every failed notification without limits, since retries can create duplicate messages.
Telegram’s current bot FAQ advises avoiding more than one message per second in a single chat and lists a 20-message-per-minute group limit; excess traffic can produce HTTP 429 responses. These are Telegram platform limits, not a guarantee that every form’s sending pattern will be accepted. See Telegram’s rate-limit FAQ.
Do you need a Telegram webhook?
No, not for a website form that sends notifications outward to Telegram. The PHP handler makes an outbound Bot API request directly. A webhook is used for Telegram updates sent inbound to your server, such as messages users send to the bot; Telegram’s advice about using a secret webhook URL path applies to that different setup. See Telegram’s webhook FAQ.
Message size and practical privacy
Telegram’s Bot API 10.3 reference, dated August 24, 2026, specifies sendMessage text of 1–4096 characters after entity parsing. Keep notifications concise and avoid sending information your managers do not need. The example caps the submitted message at 3,000 bytes, which is a PHP-side safeguard rather than Telegram’s character-limit calculation; if your site accepts long or non-ASCII text, measure and truncate according to your own policy before sending.
Form submissions may contain personal or sensitive information. Decide which fields genuinely need to reach Telegram, restrict access to the destination chat, and review the privacy and legal requirements applicable to your data and jurisdiction.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




