I’ve written about hosting a python based Telegram bot here before. This time we’ll take look at doing it with NET 6, C#, Azure Functions V4 and the still fresh execution mode called isolated process. In this mode, each function runs in a separate environment.

What we’ll cover

  • creating a sample Azure Functions project and deploying it to your Azure subscription
  • creating a Telegram Bot and using it in a webhook configuration


Check out this article for step by step instructions – https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-csharp

Setting up and deploying blank Azure Functions project

We’ll first create the blank Azure Functions project with a sample HTTP Trigger

func init TelegramFunctions --worker-runtime dotnet-isolated

cd TelegramFunctions

func new --name SetUpBot --template "HTTP trigger" --authlevel "anonymous"

The above commands should create all necessary files to run the functions. There’s one manual step you need to do to use the V4 Azure Functions. Open the .csproj file in the TelegramFunctions folder and bump the version manually from v3 to:


Now you should be ready to run the Functions, do it with this command:

func start

In the output, you should see a link to the sample HTTP trigger function called ‘SetUpBot’. It was created above with the func new command. Open the link to make sure that the Function is working properly:

Perfect! 🎊 Now let’s deploy it online. Before doing that, we first need to prepare the needed resources in Azure. Run the following scripts (make sure to update the parameters to your own names):

az login

// below creates a resource group in a specified location
az group create --name RESOURCE_GROUP_NAME --location germanywestcentral

// below creates a storage account needed to set up the functions
az storage account create --name STORAGE_ACCOUNT_NAME --location germanywestcentral --resource-group RESOURCE_GROUP_NAME --sku Standard_LRS

// below creates the functions app on a Consumption plan with isolated execution mode
az functionapp create --resource-group RESOURCE_GROUP_NAME --consumption-plan-location germanywestcentral --runtime dotnet-isolated --functions-version 4 --name FUNCTIONS_APP_NAME  --storage-account STORAGE_ACCOUNT_NAME

… and then we’ll deploy our project:

func azure functionapp publish FUNCTIONS_APP_NAME

If everything went well (hopefully), in the output you’ll see the link to your publicly available Azure Function – after opening it in your browser, you should see the exact same output as when running it locally. Your sample function is officially alive 🎉

Creating a Telegram bot

To start using the bot, we first need to create it, which is super easy:

  1. Open the Telegram app on any device and start a conversation with @botfather
  2. Send this command: /newbot
  3. Answer his questions about the bot’s name and handle
  4. He’ll responsd with the bot’s token similar to the one below:


    We’ll use it in the next steps. Make sure to keep it safe, anyone who has access to it can fully control your bot! 🚨

Telegram integration

To make things easier, we’ll use the Telegram.Bot nuget for communication with the Telegram services. Add it to your project with this command:

dotnet add package Telegram.Bot --version 17.0.0

Now we’re ready to create 2 HTTP Triggered Azure Functions, we’ll do it in the SetUpBot.cs file which you should already have in your project folder.

  • /setup – the first function will setup our bot to operate in a webhooks mode. This means that whenever anyone interacts with the bot, Telegram will send a POST request to the endpoint we specify (as you can see below, we specify the link to the second function, handleupdate)
  • /handleupdate – this function receives the Update object from Telegram services and reacts accordingly. All of the messages, replies, images etc will arrive to this endpoint. For the purposes of this tutorial, we’ll try to evaluate user’s message as a math expression and will return the result
    private const string SetUpFunctionName = "setup";
    private const string UpdateFunctionName = "handleupdate";

    public async Task RunAsync([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
        var handleUpdateFunctionUrl = req.Url.ToString().Replace(SetUpFunctionName, UpdateFunctionName,
                                            ignoreCase: true, culture: CultureInfo.InvariantCulture);
        await _botClient.SetWebhookAsync(handleUpdateFunctionUrl);

    public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
        var request = await req.ReadAsStringAsync();
        var update = JsonConvert.DeserializeObject<Telegram.Bot.Types.Update>(request);

        if (update.Type != UpdateType.Message)
        if (update.Message!.Type != MessageType.Text)

        await _botClient.SendTextMessageAsync(
        chatId: update.Message.Chat.Id,
        text: GetBotResponseForInput(update.Message.Text));

    private string GetBotResponseForInput(string text)
            if (text.Contains("pod bay doors", StringComparison.InvariantCultureIgnoreCase))
                return "I'm sorry Dave, I'm afraid I can't do that 🛰";

            return new DataTable().Compute(text, null).ToString();
            return $"Dear human, I can solve math for you, try '2 + 2 * 3' 👀";

Both functions are using the _botClient instance, which is created in the class constructor and uses the bot token from the environment variables.

    private readonly TelegramBotClient _botClient;

    public SetUpBot()
        _botClient = new TelegramBotClient(System.Environment.GetEnvironmentVariable("TelegramBotToken", EnvironmentVariableTarget.Process));

When functions are run locally, you can specify the value for the TelegramBotToken variable in the local.settings.json file. For the deployed Functions app, you can configure it with the below command:

az functionapp config appsettings set --name FUNCTIONS_APP_NAME --resource-group RESOURCE_GROUP_NAME --settings "TelegramBotToken=YOUR_BOT_TOKEN"

Let’s talk

Deploy the updated project with the same command as before:

func azure functionapp publish FUNCTIONS_APP_NAME

In the output, you’ll see 2 links to our Functions – before talking to the bot, we first need to open the /setup link, which will configure the bot to call our second function.

Then we should be ready to get some answers from the bot. Start a conversation with it on Telegram and either try to ask some math questions or try to recreate the Space Oddysey scene (at your own risk!) ☺️

Things are working as expected, that’s great! I’m positively surprised how fast the interaction is – the questions go through and back the Telegram API & Azure in a blink of an eye as you can see above 👁

Clean up

After you’re done, make sure to remove the Azure resources you’ve created, you don’t want to pay for the resources that you don’t use. Deleting the whole resource group can be done with the following command:

az group delete --name RESOURCE_GROUP_NAME

Where to go from here

Now that you know how to use Azure Functions as the brain for your bots, diving deeper into documentations might give you some nice ideas on what to do next. The API is quite rich, you can create pools, send locations, even accept payments or validate user’s identity with Telegram Passport.

Bots: An introduction for developers (official Telegram website)
Telegram.Bot nuget documentation

Also before deploying your Bot, it might be wise to think twice about the security of your API. The setup function above should probably be authenticated with a Function access key. The handleupdate function could also have a password/token in the URL, to make sure that the request comes from Telegram services.

Let me know if you’d have any questions/problems with creating the bots with Azure Functions, I’d be happy to help 🚀

Write A Comment