How to Create a Telegram Bot in PHP : Step by Step

Create a Telegram Bot in PHP


If you want your PHP app to send Telegram messages, reply to users, or trigger notifications automatically, a Telegram bot is the right tool. The setup is faster than most people expect, BotFather handles the registration, and a handful of API calls handle the rest.

This guide covers everything from creating the telegram bot to writing PHP code that handles commands like /start, replies to messages, and sends proactive notifications.

What You Can Build

Before diving in, here are a few common use cases so you can adapt the code to your actual goal:

  • Alert bot – your PHP app sends a Telegram message whenever something happens (form submission, order placed, server error)
  • Auto-reply bot – bot reads incoming messages and replies based on keywords or commands
  • Admin notification bot – sends you a Telegram ping when your website needs attention

All of these use the same API. The difference is mostly in how you structure the logic inside your PHP script.

Prerequisites

  • A Telegram account (mobile or desktop app)
  • A PHP server (any modern version – PHP 7.4 or higher)
  • For the webhook approach: a domain with a valid HTTPS certificate (Let’s Encrypt works fine)
  • Basic PHP knowledge – you don’t need a framework

How a Telegram Bot Works:

Telegram Bot is an automated software application that do some tasks repeatedly. For example when some when message on telegram than via bot, message create in google spreadsheet. This application runs inside the telegram, Using bot API you can manage HTTP requests. You can integrate telegram with other third party web service, send messages, accept payment.

Step by Step: Create a Telegram Bot in PHP

Let’s check out the step by step process of creating a telegram bot.

Step 1: Create the Bot with BotFather

BotFather is Telegram’s official bot for registering and managing bots. All new bots go through it.

  1. Open Telegram and search for @BotFather. Confirm it has the blue verified checkmark, there are fake accounts with similar names.
  2. Send /newbot to start the setup.
  3. BotFather asks for a display name – what users see in the chat header (e.g., My Alert Bot). This can be anything.
  4. Then it asks for a username – the @handle for your bot. Two rules apply here: it must be globally unique, and it must end in bot (e.g., myalert_bot or MyAlertBot). Usernames are 5–32 characters, Latin letters, numbers, and underscores only.

Once you pick a valid username, BotFather confirms and gives you an API token that looks like:

1234567890:AAFbFH5zMHmK3QeXP_ExampleTokenHere

Save this token. It’s the only thing that authenticates your PHP code with Telegram’s servers. Treat it like a password, don’t commit it to Git or paste it in public.

telegram bot token

If your token gets exposed: open BotFather, send /mybots, select your bot, go to API Token → Revoke current token. That immediately invalidates the old one.

Step 2: Test the Connection

Before writing any PHP, paste this into your browser to confirm the bot is active (replace YOUR_TOKEN):

https://api.telegram.org/botYOUR_TOKEN/getMe

You should see a JSON response like:

{
  "ok": true,
  "result": {
    "id": 1234567890,
    "is_bot": true,
    "first_name": "My Alert Bot",
    "username": "myalert_bot"
  }
}

If ok is false, the token is wrong, double check for missing or extra characters.

Step 3: Choose How to Receive Messages

There are two ways to get updates from Telegram. You pick one, they can’t run simultaneously:

MethodHow it worksBest for
getUpdatesYour script polls the API and fetches new messages on demandLocal testing, servers without HTTPS
setWebhookTelegram pushes updates to your server automatically via POSTProduction; more efficient, no polling needed

Method A: getUpdates (Polling – Good for Testing)

With polling, your PHP script calls getUpdates and processes whatever messages have arrived since the last call. No HTTPS required, which makes it ideal for local development.

Create telegram_bot.php:

<?php

$token   = 'YOUR_TOKEN'; // Never hardcode in production — use environment variables
$apiBase = 'https://api.telegram.org/bot' . $token;

// Fetch recent updates from Telegram
$response = file_get_contents($apiBase . '/getUpdates');
$data     = json_decode($response, true);

if (empty($data['result'])) {
    echo 'No new messages.';
    exit;
}

// Process each update
foreach ($data['result'] as $update) {
    if (empty($update['message'])) {
        continue; // Skip non-message updates (e.g. edited messages)
    }

    $chatId  = $update['message']['chat']['id'];
    $text    = $update['message']['text'] ?? '';

    // Respond to /start command
    if ($text === '/start') {
        $reply = 'Hello! I am your bot. Send me any message and I will reply.';
    } else {
        $reply = 'You said: ' . $text;
    }

    // Send the reply
    $params = http_build_query([
        'chat_id' => $chatId,
        'text'    => $reply,
    ]);

    file_get_contents($apiBase . '/sendMessage?' . $params);
}

echo 'Done.';

How to test it: Send a message to your bot in Telegram first, then run this script by visiting its URL or executing it with php telegram_bot.php. The bot will reply to each queued message.

The downside: you have to trigger the script manually each time. Webhooks solve this.

Method B: setWebhook (Recommended for Production)

With a webhook, Telegram sends a POST request to your PHP file every time the bot receives a message. Your script runs automatically – no polling loop, no cron job.

Register the Webhook

Run this URL in your browser once (replace both placeholders):

https://api.telegram.org/botYOUR_TOKEN/setWebhook?url=https://yourdomain.com/telegram_webhook.php

You’ll get:

{"ok":true,"result":true,"description":"Webhook was set"}

Key requirements:

  • Your webhook URL must use HTTPS with a valid certificate. Telegram accepts ports 443, 80, 88, and 8443.
  • Once a webhook is registered, getUpdates stops working for that bot until you call deleteWebhook.
  • To remove the webhook: https://api.telegram.org/botYOUR_TOKEN/deleteWebhook

The Webhook Handler (with Bot Commands)

This is where the real logic lives. Create telegram_webhook.php at the path you registered:

<?php

$token   = 'YOUR_TOKEN';
$apiBase = 'https://api.telegram.org/bot' . $token;

// Telegram sends the update as a raw JSON POST body
$input = file_get_contents('php://input');
$data  = json_decode($input, true);

// Only process updates that contain a text message
if (empty($data['message']['text'])) {
    http_response_code(200); // Always respond 200 — Telegram retries on any other status
    exit;
}

$chatId = $data['message']['chat']['id'];
$text   = trim($data['message']['text']);

// Handle bot commands
if ($text === '/start') {
    $reply = "Welcome! Here's what I can do:\n/start — Show this message\n/help — Get help\nOr just type anything and I'll echo it back.";
} elseif ($text === '/help') {
    $reply = 'Send me any message and I will reply. You can also use /start to see available commands.';
} else {
    // Echo back whatever the user typed
    $reply = 'You said: ' . $text;
}

// Send the reply via sendMessage
$params = http_build_query([
    'chat_id' => $chatId,
    'text'    => $reply,
]);

file_get_contents($apiBase . '/sendMessage?' . $params);

http_response_code(200);

Why http_response_code(200) is required: If your script returns a non-200 status, Telegram assumes delivery failed and retries the same update multiple times. Always return 200 — even if you decide to ignore an update.

Why php://input instead of $_POST: Telegram sends updates as a raw JSON body, not as form-encoded data. $_POST will be empty. file_get_contents('php://input') reads the raw body correctly.

How to Send a Message Proactively (Without Waiting for a User)

This is one of the most common follow-up questions: what if you want your PHP application to push a message to Telegram on its own for example, when a new order comes in?

You need the recipient’s chat_id. Users must message your bot at least once, Telegram won’t let you initiate contact otherwise. Once they do, store that chat_id in your database.

Then, from any PHP script:

<?php

$token   = 'YOUR_TOKEN';
$chatId  = 123456789; // The stored chat_id of the recipient
$message = 'New order received! Order #1042 is ready for review.';

$params = http_build_query([
    'chat_id' => $chatId,
    'text'    => $message,
]);

$response = file_get_contents(
    'https://api.telegram.org/bot' . $token . '/sendMessage?' . $params
);

$result = json_decode($response, true);

if ($result['ok']) {
    echo 'Message sent successfully.';
} else {
    echo 'Error: ' . $result['description'];
}

This is the pattern behind Telegram notification bots, a form handler, a cron job, or a payment webhook calls this code and pushes a message straight to your Telegram.

Read detailed guide on : How to Make a Discord Bot with PHP

Troubleshooting Common Issues

Bot doesn’t respond after setting the webhook

Check the webhook status:

https://api.telegram.org/botYOUR_TOKEN/getWebhookInfo

Look at the last_error_message field. Common causes: your server returned an error, the file path is wrong, or the SSL certificate is not valid.

getUpdates returns an empty result array

Either nobody has messaged the bot yet, or a webhook is still registered. Call deleteWebhook first, then send a message to the bot and try getUpdates again.

sendMessage fails silently

Print the raw response from file_get_contents to see Telegram’s error. The most common cause is a wrong chat_id. Check the full $data array to confirm what Telegram actually sent.

Token returns 401 Unauthorized

The token is invalid or has been revoked. Generate a new one via BotFather: /mybots → select your bot → API Token → Revoke.

Webhook set successfully but script errors out

Check your server’s PHP error log. Common issues: json_decode fails on empty input (happens during browser testing, the webhook only works when Telegram calls it via POST), or the php://input stream is empty on some hosting configs.

Using cURL Instead of file_get_contents

file_get_contents is fine for simple bots, but cURL gives you HTTP status codes and more reliable error handling. Here’s the sendMessage call rewritten with cURL:

<?php

function sendTelegramMessage(string $token, int $chatId, string $text): array
{
    $url  = 'https://api.telegram.org/bot' . $token . '/sendMessage';
    $data = ['chat_id' => $chatId, 'text' => $text];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // Keep SSL verification on

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($response === false) {
        return ['ok' => false, 'description' => 'cURL error'];
    }

    return json_decode($response, true);
}

// Usage
$result = sendTelegramMessage('YOUR_TOKEN', 123456789, 'Hello from cURL!');

if (!$result['ok']) {
    error_log('Telegram error: ' . $result['description']);
}

Use this pattern once your bot is handling real traffic or when you need to debug API responses properly.

Conclusion:

This is a very straightforward way to create a telegram bot, just followed it step by step and you are good to go. If you found this tutorial helpful please share it with others and leave your valuable feedback. Thanks enjoy..

Similar Posts

One Comment

  1. A simple, yet straightforward and working sample.
    Struggled on other sites with all their technical mumbo jumbo.
    Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *