Cover image for Write and deploy Golang Telegram Bot

Write and deploy Golang Telegram Bot

talentlessguy profile image v 1 r t l Updated on ・5 min read


Most of the tutorials use Python for writing bots because it is rather simple and also almost everyone knows Python. But what about other languages? Maybe someone doesn't like Python or it is slow for some tasks? In this tutorial I'll show how to build a telegram bot with Go and deploy it on Heroku.

Install the things

All the instructions will be for Linux based distros because the author uses Linux (Ubuntu)

You need to install Go:

# Debian / Ubuntu

sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install golang-go

# Fedora

sudo dnf install golang

# Arch
sudo pacman -S go

# OpenSUSE
sudo zypper install golang

For other platforms, see Download page.

Once Golang is set up, let's create a new project.

First, we should create a repo on GitHub, then initialize go module and then download telebot (go library for writing bots) and create our golang code file:

git clone https://github.com/<USER>/golang-tg-bot
cd golang-tg-bot
# Enter github URL of ur repo or any random name
go mod init github.com/<USER>/golang-tg-bot
go get -u -v gopkg.in/tucnak/telebot.v2
touch main.go

Getting Telegram Bot Token

Open Telegram app, search for @BotFather and start the chat. Send /newbot command and follow the instructions. After completing the initial steps, you’ll get —

  • your TOKEN
  • telegram bot URL
  • link on docs

If you click the link (e.g. telegram bot URL) you'll see something like this:

Of course not with these wallpapers but you'll definetely see bot name, and a button "Start". If you press /start you'll launch a bot client and nothing will happen. Because we haven't done anything yet! So let's start writing the bot.

Setting up Heroku

On Heroku, create a new app. Then choose production environment.

After clicking on item in this menu, you'll see something like this:

You won't see any logs because we haven't setup our bot.

Go to Settings, there connect your repository to Heroku app:

Now we should add our telegram token and app url to Config Vars. Put your token and name of the app (e.g. <NAME_OF_YOUR_APP>.herokuapp.com) there.

We'll need them when setting webhooks so our bot will behave like a web server.

Configuration is done here, let's go to code!

Configuring Bot


We grab environment variables, then setup webhook that will be running on Heroku's app URL.

package main

import (
    tb "gopkg.in/tucnak/telebot.v2"

func main() {
    var (
        port      = os.Getenv("PORT")       // sets automatically
        publicURL = os.Getenv("PUBLIC_URL") // you must add it to your config vars
        token     = os.Getenv("TOKEN")      // you must add it to your config vars

    webhook := &tb.Webhook{
        Listen:   ":" + port,
        Endpoint: &tb.WebhookEndpoint{PublicURL: publicURL},

Configuring telebot

After webhook being set up we can create an instance of our bot. Here we use our webhook as a Poller, a thing that looks for updates.

package main

import (

    tb "gopkg.in/tucnak/telebot.v2"

func main() {
    var (
        port      = os.Getenv("PORT")
        publicURL = os.Getenv("PUBLIC_URL") // you must add it to your config vars
        token     = os.Getenv("TOKEN")      // you must add it to your config vars

    webhook := &tb.Webhook{
        Listen:   ":" + port,
        Endpoint: &tb.WebhookEndpoint{PublicURL: publicURL},

    pref := tb.Settings{
        Token:  token,
        Poller: webhook,

    b, err := tb.NewBot(pref)
    if err != nil {

Writing handlers

Handlers for commands are pretty much similar to middleware in Node.js but instead of routes we handle commands, like /hello, or /get_apples 10.

Hello World

Our first handler will be "Hello World":

b.Handle("/hello", func(m *tb.Message) {
    b.Send(m.Sender, "Hi!")

Let's deploy our bot to check if it works. Push your changes to repository, then go to Heroku and check if app is deployed.

If it is succeeded, then go to Telegram bot and entering /hello. It will output "Hi!".

Getting user input

To get user input, we need to grab m.Text - text of a message. You can also get other info from message struct, check GoDoc.

b.Handle("/hello", func(m *tb.Message) {
      b.Send(m.Sender, "You entered "+m.Text)

If you try it, it will output something like:

Any text after the command will also be shown. For text without a command, use Payload:

b.Handle("/hello", func(m *tb.Message) {
       b.Send(m.Sender, "You entered "+m.Payload)


Telegram bots have different types of buttons, Inline, they are attached to some message, and Reply buttons which appear on your message panel.

We will implement first ones because they are easier to write.

First, let's define the buttons. telebot has a special struct for it, called tb.InlineButton:

inlineBtn1 := tb.InlineButton{
    Unique: "moon",
    Text:   "Moon 🌚",

inlineBtn2 := tb.InlineButton{
    Unique: "sun",
    Text:   "Sun 🌞",

After defining the buttons, we should write handlers for them. In Telegram API, you need to write a response callback to each button, even if it doesn't show any alerts or anything else. If you don't write callbacks, button callback will be endlessly loading.

b.Handle(&inlineBtn1, func(c *tb.Callback) {
        // Required for proper work
    b.Respond(c, &tb.CallbackResponse{
        ShowAlert: false,
        // Send messages here
    b.Send(c.Sender, "Moon says 'Hi'!")

Let's do the same for second button:

b.Handle(&inlineBtn2, func(c *tb.Callback) {
    b.Respond(c, &tb.CallbackResponse{
        ShowAlert: false,
    b.Send(c.Sender, "Sun says 'Hi'!")

Cool, now we need to defne a keyboard for buttons. It is a "set" of them that are attached to a message. Even if you have only button you still need to define a keyboard:

inlineKeys := [][]tb.InlineButton{
    []tb.InlineButton{inlineBtn1, inlineBtn2},

Here we created an array of arrays of tb.InlineButton which contains one array with type tb.InlineButton which contains our buttons.

One small thing left - a handler for a command, say /pick_time:

b.Handle("/pick_time", func(m *tb.Message) {
        "Day or night, you choose",
        &tb.ReplyMarkup{InlineKeyboard: inlineKeys})

Our command is ready, let's test it (you need to push code for Heroku to update the app)!



As you can see our bot is working and has some nice buttons. For other options, such as stickers and sending files, visit repo readme and godoc.

Posted on by:

talentlessguy profile

v 1 r t l


16yo nullstack dev, OSSer ⚡, expert in nothing


Editor guide

just an update you will need to add b.Start() to actually start listening on the port.


ah yes, forgot to add, sorry


Привет! Сделал все по вашейинструкции, но при deploy на heroku ловлю такую ошибку
App not compatible with buildpack, поиски в гугле результатов не дали.
Может вы сталкивались с этим?


Возможно вы выбрали не тот язык для приложения на Heroku. Его можно переключить в настройках


В смысле buildpack?
Попробовал все что нашел, все равно не работает.


Thanks. But can you tell me the name of the game in your wallpaper


Hyper Light Drifter