Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

mtgo-labs/mtgo

Open more actions menu
MTGo

mtgo (MTProto Go)

A fast, idiomatic Go client for the Telegram MTProto API.

Engineering priorities are security and correctness, measured performance, low latency, and minimal raw-protocol overhead.

Note: mtgo stands for MTProto Go. It is a Telegram client library and has no relation to Magic: The Gathering Online.

License Go Reference Documentation skills.sh Telegram

Features

  • Full MTProto 2.0 — encryption, key generation, CDNs, file transfers
  • High-level client API — messages, chats, media, inline, stories, payments, business connections
  • Handler-based updates — register handlers with filters, priorities, and handler groups
  • Middleware — invoker-level (RPC calls) and handler-level (update dispatch) middleware chains
  • Plugin system — lifecycle plugins with Start/Stop hooks
  • Multi-client — run multiple bots/users in one process with Compose or Idle
  • Session import/export — Telethon, Pyrogram, GramJS, mtcute, tdesktop session formats
  • Storage backendsSQLite, PostgreSQL, MongoDB, or bring your own adapter
  • MTProxy support — dd/ee/simple secrets with obfuscated2 and fake TLS
  • WebSocket transport — MTProto over WebSocket for restrictive networks
  • HTTP transport — bounded MTProto-over-HTTP with encrypted long polling and endpoint failover
  • Auto-reconnect — exponential backoff with jitter and configurable max attempts
  • Health checks — periodic ping/pong keepalive with configurable timeout
  • Generated TL layer — auto-generated from Telegram schemas; update with one command
  • Pure Go — no CGO required (SQLite via modernc.org/sqlite)

Quick Start

# Install as a Go module
go get github.com/mtgo-labs/mtgo

# Install the CLI tool
go install github.com/mtgo-labs/mtgo-cli/cmd/mtgo-cli@latest

# Install the Agent Skill for Claude Code, Codex, Cursor, etc.
npx skills add mtgo-labs/mtgo
# or with full URL
npx skills add https://github.com/mtgo-labs/mtgo
package main

import (
    "fmt"
    "log"
    "os"

    "github.com/mtgo-labs/mtgo/telegram"
    "github.com/mtgo-labs/mtgo/telegram/types"
)

func main() {
    client, err := telegram.NewClient(apiID, apiHash, &telegram.Config{
        BotToken:    os.Getenv("BOT_TOKEN"),
        SessionName: "my_bot",
        SavePeers:   true,
    })
    if err != nil {
        log.Fatal(err)
    }

    client.OnMessage(func(client *telegram.Client, msg *types.Message) {
        msg.Reply(msg.Text)
    }, telegram.Private)

    if err := client.Connect(0); err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    fmt.Println("bot is running")
    client.Idle()
}

See examples/ for more: middleware, conversations, SQLite, MongoDB, keyboards, media, MTProxy, webapp, and more.

Authentication

Bot

client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    BotToken: "123456:ABC-DEF",
})

User (Phone Number)

client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    PhoneNumber: "+1234567890",
})
client.Connect(0)
// Terminal prompts for code/password automatically

QR Login

client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{})
client.QRLogin(context.Background())
// Displays QR code link for Telegram mobile scanning

Session Strings

Import existing sessions from other frameworks:

import "github.com/mtgo-labs/mtgo/session"

// From Telethon
client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    SessionString: session.MustTelethon("1BVusO..."),
})

// From Pyrogram
client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    SessionString: session.MustPyrogram("BAAJbwI..."),
})

Handlers and Filters

// Command handler
client.OnMessage(func(client *telegram.Client, msg *types.Message) {
    msg.Reply("Welcome!")
}, telegram.Command("start"))

// Regex filter
client.OnMessage(func(client *telegram.Client, msg *types.Message) {
    msg.Reply("Got a number!")
}, telegram.Regex(`\d+`))

// Combined filters
client.OnMessage(handlePrivate, telegram.Private.And(telegram.HasText))

// Callback queries
client.OnCallbackQuery(func(client *telegram.Client, cb *types.CallbackQuery) {
    cb.Answer("Pressed!", false)
})

Built-in filters: Private, Group, HasText, Command, Regex, Media, Photo, Video, Document, Audio, Voice, VideoNote, Sticker, Animation, Contact, Location, Venue, Poll, Game, Forwarded, Reply, Outgoing, and composable with .And(), .Or(), .Not().

Middleware

Two middleware levels for different concerns:

Level Method Intercepts Use case
Invoker UseInvokerMiddleware Outgoing RPC calls Rate limiting, flood wait, logging, metrics
Handler UseMiddleware Incoming update dispatch Auth, i18n, conversation state
// Invoker middleware (wraps RPC calls)
mw := floodwait.New()
client.UseInvokerMiddleware(mw.Middleware())

// Handler middleware (wraps update dispatch)
client.UseMiddleware(authMiddleware, -10) // lower priority = outermost
client.UseMiddleware(loggingMiddleware, 0)

Writing a Custom Invoker Middleware

An invoker middleware wraps tg.Invoker to intercept, inspect, and modify RPC calls:

import (
    "context"
    "io"

    "github.com/mtgo-labs/mtgo/tg"
)

// SilentMiddleware forces all outgoing messages to be silent.
func SilentMiddleware() telegram.InvokerMiddleware {
    return func(next tg.Invoker) tg.Invoker {
        return tg.InvokerFunc(func(ctx context.Context, input tg.TLObject, decode func(io.Reader) (tg.TLObject, error)) (tg.TLObject, error) {
            // Type-assert and modify request parameters before the call
            if req, ok := input.(*tg.MessagesSendMessageRequest); ok {
                req.Silent = true
                req.SetFlags() // required after modifying flag-controlled fields
            }
            return next.RPCInvoke(ctx, input, decode)
        })
    }
}

// Register it (first = outermost)
client.UseInvokerMiddleware(SilentMiddleware())

Ready-made middlewares: floodwait, ratelimit.

Plugins

Plugins implement the Plugin interface to add lifecycle-aware, modular functionality:

import (
    "context"
    "log"

    "github.com/mtgo-labs/mtgo/telegram"
)

// MetricsPlugin tracks bot usage.
type MetricsPlugin struct {
    client      *telegram.Client
    messageCount int64
}

func (p *MetricsPlugin) Name() string { return "metrics" }

func (p *MetricsPlugin) Start(ctx context.Context, client *telegram.Client) error {
    p.client = client
    log.Printf("[%s] started", p.Name())
    return nil
}

func (p *MetricsPlugin) Stop(ctx context.Context) error {
    log.Printf("[%s] stopped — processed %d messages", p.Name(), p.messageCount)
    return nil
}
// Register plugins before connecting
client.Use(i18nPlugin)
client.Use(conversationsPlugin)
client.Use(&MetricsPlugin{})

// Plugins start/stop automatically with the client
client.Connect(0)

Available plugins: conversations, i18n.

Storage

SQLite

import (
    "github.com/mtgo-labs/storage"
    "github.com/mtgo-labs/storage/sqlite"
)

ext, _ := sqlite.Open("session.db")
defer ext.Close()

client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    BotToken:    botToken,
    SessionName: "my_bot",
    Storage:     storage.NewAdapter(ext),
})

PostgreSQL

import (
    "github.com/mtgo-labs/storage"
    "github.com/mtgo-labs/storage/postgres"
)

ext, _ := postgres.Open(postgres.Config{
    Host:     "localhost",
    Port:     5432,
    User:     "postgres",
    Password: os.Getenv("PG_PASSWORD"),
    Database: "mtgo_sessions",
    SSLMode:  "disable",
})
defer ext.Close()

client, _ := telegram.NewClient(apiID, apiHash, &telegram.Config{
    BotToken:    botToken,
    SessionName: "my_bot",
    Storage:     storage.NewAdapter(ext),
})

Backends: SQLite, PostgreSQL, MongoDB. See the storage repo for custom adapter docs.

HTTP Transport

Enable MTProto-over-HTTP only when raw TCP or WebSocket is unavailable:

cfg := telegram.Config{
    HTTPTransport: &telegram.HTTPTransportConfig{TLS: true},
}
client, err := telegram.NewClient(apiID, apiHash, &cfg)

MTGO generates the DC /api endpoints automatically. URLs can override them for a custom gateway. HTTP transport is mutually exclusive with WebSocket and MTProxy; SOCKS and HTTP CONNECT proxy settings still apply.

Telemetry

Set Config.Telemetry to receive structured RPC and connection observations without adding a dependency to the raw MTProto core. OpenTelemetry users can use the optional adapter:

import mtgootel "github.com/mtgo-labs/mtgo/telegram/otel"

telemetry, err := mtgootel.New(mtgootel.Config{})
if err != nil {
    return err
}
cfg.Telemetry = telemetry

The adapter records RPC duration and attempts, connection events, flood waits, and corresponding spans through the configured or global OpenTelemetry providers.

Multi-Client — Manage Multiple Client Instances

Each telegram.NewClient() call creates a separate, independent mtgo client instance (a Telegram bot or user session). Run multiple bots, user accounts, or a mix of both in a single process and block until all stop:

// Create independent MTGO client instances
bot1, err := telegram.NewClient(apiID, apiHash, &telegram.Config{
    BotToken:    token1,
    SessionName: "bot1",
})
if err != nil {
    log.Fatal(err)
}

bot2, err := telegram.NewClient(apiID, apiHash, &telegram.Config{
    BotToken:    token2,
    SessionName: "bot2",
})
if err != nil {
    log.Fatal(err)
}

// Register handlers per client
bot1.OnMessage(func(ctx *telegram.Context) {
    ctx.Reply("Bot 1 here!")
}, telegram.Private)

bot2.OnMessage(func(ctx *telegram.Context) {
    ctx.Reply("Bot 2 here!")
}, telegram.Private)

// Connect both clients
bot1.Connect(0)
bot2.Connect(0)

// Compose starts all clients in goroutines and blocks until any stops.
// It returns an error if any client fails to start.
if err := telegram.Compose(bot1, bot2); err != nil {
    log.Fatal(err)
}

// Alternatively, call telegram.Idle() to block until ALL registered
// clients stop (every NewClient auto-registers).

Project Structure

cmd/            Code generators (TL schema, error types)
compiler/       TL compiler and templates
docs/           API reference
examples/       Working examples
internal/       MTProto internals (crypto, session, transport)
session/        Session string import/export
tg/             Generated TL types (do not edit directly)
tgerr/          Generated error types
telegram/       High-level client API, handlers, filters, middleware
mtproxy/        MTProxy obfuscated2/fake-TLS transport

Code Generation

# Regenerate TL types from schema
go run cmd/tlgen/main.go

# Regenerate error types
go run cmd/errgen/main.go

Do not edit generated files directly. Modify the schema in compiler/ or cmd/ instead.

Contributing

See CONTRIBUTING.md for development setup, code style, and PR process.

Security

See SECURITY.md for reporting vulnerabilities.

License

Licensed under the Apache License 2.0.

Ecosystem

Repository Description
mtgo-cli Fast MTProto CLI — invoke TL methods, test bots, manage groups from the terminal
mtgo-bot-api Self-hosted Bot API server — drop-in Go reimplementation of the official Telegram Bot API
mtgo-ipc Standalone IPC bridge — JSON-RPC over Unix socket, lets any language drive mtgo
session-converter Convert session strings between Telethon, Pyrogram, GramJS, mtcute, MTKruto, gogram, gotgproto + SQLite import
device-manager Generate realistic Telegram client device profiles — Android, iOS, macOS, Desktop, Web
wasm Run mtgo in the browser via WebAssembly — WebSocket transport + JS bridge, available on npm as @mtgo-labs/wasm
storage Persistent storage adapters (SQLite, PostgreSQL, MongoDB)
plugins Official plugins (conversations, i18n)
middlewares Invoker middleware (flood wait, rate limiting)
plugins-template Template for new plugins
middlewares-template Template for new middlewares

About

Fast, idiomatic Go client for Telegram MTProto: bots, userbots, generated TL types, middleware, plugins, storage, MTProxy, WebSocket, and auto-reconnect.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.