Bot
Telegram Bot API Go framework
Install / Use
/learn @go-telegram/BotREADME
Golang Telegram Bot
✅ Present in the list of libraries https://core.telegram.org/bots/samples#go
Supports Bot API version: 9.5 from March 1, 2026
It's a Go zero-dependencies telegram bot framework
A simple example echo-bot:
package main
import (
"context"
"os"
"os/signal"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)
// Send any text message to the bot after the bot has been started
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
opts := []bot.Option{
bot.WithDefaultHandler(handler),
}
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", opts...)
if err != nil {
panic(err)
}
b.Start(ctx)
}
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: update.Message.Chat.ID,
Text: update.Message.Text,
})
}
You can find more examples in the examples folder.
To run the examples, set the EXAMPLE_TELEGRAM_BOT_TOKEN environment variable to your bot token.
Getting started
Go version: 1.18
Install the dependencies:
go get -u github.com/go-telegram/bot
Initialize and run the bot:
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER")
b.Start(context.TODO())
On create bot will call the getMe method (with 5 sec timeout). And returns error on fail.
If you want to change this timeout, use option bot.WithCheckInitTimeout
You can define a default handler for the bot:
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", bot.WithDefaultHandler(handler))
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
// this handler will be called for all updates
}
Webhooks
If you want to use webhooks, instead of using bot.Start, you should use the bot.StartWebhook method to start the bot.
Also, you should use bot.WebhookHandler() method as HTTP handler for your server.
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
opts := []bot.Option{
bot.WithDefaultHandler(handler),
bot.WithWebhookSecretToken(os.Getenv("EXAMPLE_TELEGRAM_WEBHOOK_SECRET_TOKEN"))
}
b, _ := bot.New(os.Getenv("EXAMPLE_TELEGRAM_BOT_TOKEN"), opts...)
// call methods.SetWebhook if needed
go b.StartWebhook(ctx)
http.ListenAndServe(":2000", b.WebhookHandler())
// call methods.DeleteWebhook if needed
}
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: update.Message.Chat.ID,
Text: update.Message.Text,
})
}
Also, you can manually process updates with bot.ProcessUpdate method.
update := models.Update{}
json.NewDecoder(req.Body).Decode(&update)
b.ProcessUpdate(ctx, &update)
Middlewares
You can use middlewares with WithMiddlewares(middlewares ...Middleware) option.
See an example in examples
Available methods
All available methods are listed in the Telegram Bot API documentation
You can use all these methods as bot funcs. All methods have name like in official documentation, but with capital first letter.
bot.SendMessage, bot.GetMe, bot.SendPhoto, etc
All methods have signature (ctx context.Context, params <PARAMS>) (<response>, error).
Except GetMe, Close and Logout which have no params
<PARAMS> is a struct with fields that corresponds to Telegram Bot API parameters.
All Params structs have name like for corresponded methods, but with Params suffix.
SendMessageParams for SendMessage method etc.
You should pass params by pointer
bot.SendMessage(ctx, &bot.SendMessageParams{...})
Options
You can use options to customize the bot.
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", opts...)
Options list (see options.go for more details)
WithCheckInitTimeout(timeout time.Duration)- timeout for check init botWithMiddlewares(middlewares ...Middleware)- add middlewaresWithMessageTextHandler(pattern string, matchType MatchType, handler HandlerFunc)- add handler for Message.Text fieldWithCallbackQueryDataHandler(pattern string, matchType MatchType, handler HandlerFunc)- add handler for CallbackQuery.Data fieldWithPhotoCaptionHandler- add handler for Message.Caption fieldWithDefaultHandler(handler HandlerFunc)- add default handlerWithDebug()- enable debug modeWithErrorsHandler(handler ErrorsHandler)- add errors handlerWithDebugHandler(handler DebugHandler)- add debug handlerWithHTTPClient(pollTimeout time.Duration, client HttpClient)- set custom http clientWithServerURL(serverURL string)- set server urlWithSkipGetMe()- skip call GetMe on bot initWithAllowedUpdates(params AllowedUpdates)- set allowed_updates for getUpdates methodWithUpdatesChannelCap(cap int)- set updates channel capacity, by default 1024WithWebhookSecretToken(webhookSecretToken string)- set X-Telegram-Bot-Api-Secret-Token header sent from telegram servers to confirm validity of updateWithWorkers- set the number of workers that are processing the Updates channel, by default 1UseTestEnvironment()- use test environmentWithNotAsyncHandlers()- allows to run handlers in the main goroutineWithInitialOffset(offset int64)- allows to set initial offset for getUpdates method
Message.Text and CallbackQuery.Data handlers
For your convenience, you can use Message.Text, CallbackQuery.Data and Message.Caption handlers.
An example:
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER")
b.RegisterHandler(bot.HandlerTypeMessageText, "/start", bot.MatchTypeExact, myStartHandler)
b.Start(context.TODO())
also you can use bot init options
WithMessageTextHandlerandWithCallbackQueryDataHandler
In this example, the handler will be called when the user sends /start message. All other messages will be handled by the default handler.
Handler Types:
HandlerTypeMessageText- for Update.Message.Text fieldHandlerTypeCallbackQueryData- for Update.CallbackQuery.Data fieldHandlerTypeCallbackQueryGameShortName- for Update.CallbackQuery.GameShortName fieldHandlerTypePhotoCaption- for Update.Message.Caption field
RegisterHandler returns a handler ID string. You can use it to remove the handler later.
b.UnregisterHandler(handlerID)
Match Types:
MatchTypeExactMatchTypePrefixMatchTypeContainsMatchTypeCommandMatchTypeCommandStartOnly
For
MatchTypeCommandandMatchTypeCommandStartOnlyusage see an example
You can use RegisterHandlerRegexp to match by regular expression.
re := regexp.MustCompile(`^/start`)
b.RegisterHandlerRegexp(bot.HandlerTypeMessageText, re, myStartHandler)
If you want to use custom handler, use RegisterHandlerMatchFunc
matchFunc := func(update *models.Update) bool {
// your checks
return true
}
b.RegisterHandlerMatchFunc(bot.HandlerTypeMessageText, matchFunc, myHandler)
InputFile
For some methods, like SendPhoto, SendAudio etc, you can send file by file path or file contents.
To send a file by URL or FileID, you can use &models.InputFileString{Data: string}:
// file id of uploaded image
inputFileData := "AgACAgIAAxkDAAIBOWJimnCJHQJiJ4P3aasQCPNyo6mlAALDuzEbcD0YSxzjB-vmkZ6BAQADAgADbQADJAQ"
// or URL image path
// inputFileData := "https://example.com/image.png"
params := &bot.SendPhotoParams{
ChatID: chatID,
Photo: &models.InputFileString{Data: inputFileData},
}
bot.SendPhoto(ctx, params)
To send an image file by its contents, you can use &models.InputFileUpload{Filename: string, Data: io.Reader}:
fileContent, _ := os.ReadFile("/path/to/image.png")
params := &bot.SendPhotoParams{
ChatID: chatID,
Photo: &models.InputFileUpload{Filename: "image.png", Data: bytes.NewReader(fileContent)},
}
bot.SendPhoto(ctx, params)
InputMedia
For methods like SendMediaGroup or EditMessageMedia you can send media by file path or file contents.
Official documentation InputMedia
field
media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://<file_attach_name>” to upload a new one using multipart/form-data under <file_attach_name> name.
If you want to use attach:// format, you should to define MediaAttachment field with file content reader.
fileContent, _ := os.ReadFile("/path/to/image.png")
media1 := &models.InputMediaPhoto{
Media: "https://telegram.org/img/t_logo.png",
}
media2 := &models.InputMediaPhoto{
Media: "attach://image.png",
Caption: "2",
MediaAttachment: bytes.NewReader(fileContent),
}
params := &bot.SendMediaGroupParams{
ChatID: update.Message.Chat.ID,
Media: []models.InputMedia{
media1,
media2,
},
}
bot.SendMediaGroup(ctx, params)
InputSticker
For CreateNewStickerSet method you can send sticker by file path or file contents.
[Official documentation InputSticker]((https://core.telegram.org/bots/api#inputsticker)
field
sticker: The added sti
Related Skills
node-connect
341.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
341.8kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
84.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
341.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
