How to Build a Telegram Bot with Claude Code
Learn how to create a Telegram bot using Claude Code with step-by-step guidance and best practices for smooth integration.

Building a Telegram bot with Claude Code is one of the faster bot development paths available. The Bot API is clean, the library options are mature, and Claude Code generates correct handler code when the command structure is defined upfront.
The architecture is straightforward: create the bot through BotFather, store the token, and give Claude Code a clear CLAUDE.md with the command list and library choice. From there, it builds command handlers, webhook configuration, and conversation flows accurately from the first prompt.
Key Takeaways
- BotFather comes before code: The bot token is required for every API call. Create the bot in Telegram before Claude Code writes the first line.
- grammY is the recommended library: grammY is TypeScript-first, actively maintained, and better typed than the older
node-telegram-bot-api. - Polling for development, webhook for production: Polling works without a public URL. Webhooks require HTTPS and are the production standard.
- Define commands before building handlers: Providing the complete command list in CLAUDE.md means Claude Code generates all handlers in one pass with consistent structure.
- The
ctxobject is the core pattern: Every grammY handler receives the context object containing the message, chat, user, and reply methods. Specify what it contains and Claude Code uses it correctly. - Polling requires a persistent server: Unlike serverless functions, polling bots need a continuously running process. Railway and Fly.io handle this cleanly.
What Do You Need Before Writing Any Code?
Three things are required before Claude Code can build a useful Telegram bot: a bot token from BotFather, a clear one-sentence description of the bot's purpose, and Node.js 18+ installed.
Everything else follows from these. Without the token, no API call works. Without a purpose statement, Claude Code generates generic handlers that do not reflect what the bot needs to do.
- Create the bot via BotFather: Open Telegram, search for
@BotFather, send/newbot, and follow the prompts. BotFather returns a token in the format123456789:ABCdefGHI.... - Store the token immediately in
.env: AddTELEGRAM_BOT_TOKEN=your_token_hereto.envbefore writing any code. Never hardcode the token in source files. - Write a one-sentence purpose statement: "Respond to
/checkcommands with current server status" is a buildable spec. "A helpful bot" is not. Write this before opening Claude Code. - Confirm Node.js 18+: grammY requires Node.js 18 or higher. Run
node --versionto confirm before starting the project. - Set up a test group or channel: Some bot features, like group commands and inline queries, can only be tested in an actual Telegram chat during development.
How Do You Set Up the Bot Project?
Initialise with npm, install grammY, and write CLAUDE.md before generating any handler code. The CLAUDE.md is what turns Claude Code from a general TypeScript generator into a Telegram bot developer that knows your specific project.
The entry file structure is the first thing to generate. A clean src/index.ts that creates the bot instance, registers handlers, and starts polling or sets the webhook gives Claude Code a consistent scaffold to build on.
- Initialise and install dependencies: Run
npm init -y, thennpm install grammy, thennpm install -D typescript ts-node @types/nodefor TypeScript. - CLAUDE.md must include: bot purpose, library (
grammy), update method (polling for development), the complete command list with descriptions, and all environment variable names. - Generate the entry file first: Prompt Claude Code to create
src/index.tswith the bot instance, handler registration, and polling start before writing any feature code. - TypeScript configuration: Ask Claude Code to generate
tsconfig.jsonwith"target": "ES2020"and"moduleResolution": "node16". grammY requires modern module resolution. - File structure in CLAUDE.md: List
src/commands/,src/handlers/,src/lib/, andsrc/index.tsso Claude Code creates files in the right locations from the first prompt.
For CLAUDE.md and project structure principles that apply across any Claude Code build, the full stack project setup principles guide covers the approach in depth.
Webhook vs Polling: Which Should You Use?
Use polling for local development and low-traffic bots. Use webhooks in production. This is not a compromise: polling is fully capable for development environments, and webhooks are the production standard for reasons of efficiency and hosting compatibility.
The practical distinction is simple: polling works without a public URL, which makes it the default for local development. Webhooks require a public HTTPS URL and a valid SSL certificate, which production hosting provides automatically.
- Polling for development: Configure
bot.start()in your development entry point. The bot runs withts-node src/index.tsand prints updates directly to the terminal. - Webhook for production: Prompt Claude Code to call
bot.api.setWebhook(process.env.WEBHOOK_URL)on startup to register the production URL with Telegram's API. - Express integration for webhooks: In production, grammY's webhook handler integrates with Express. Ask Claude Code for an Express server with a
/webhookPOST route callingbot.handleUpdate(req.body). - ngrok for local webhook testing: If you need to test webhooks locally before deploying, ngrok creates a public HTTPS tunnel to localhost. This is optional since polling handles most development cases.
- One update method per environment: Document the update method in CLAUDE.md so Claude Code does not mix polling and webhook configuration across files.
How Do You Handle Commands and Conversation Flow?
Every Telegram bot's logic is built around command handlers and message handlers. Claude Code generates clean handler structures when the full command list is defined in CLAUDE.md before any handler code is written.
The grammY ctx object is the core pattern across every handler. It contains the message, the chat ID, the user, the bot API instance, and the reply methods. Telling Claude Code what ctx provides means it uses it correctly without needing correction.
- Basic command handler pattern:
bot.command('start', ctx => ctx.reply('Hello!'))is the pattern. Prompt Claude Code to generate a handler for each command in the CLAUDE.md list. - Register commands with BotFather: Include
bot.api.setMyCommands([...])in the entry file startup so command autocomplete works in Telegram for all users. - Message handlers for free-form input:
bot.on('message:text', ctx => ...)handles any text message outside of commands. Add these alongside command handlers for keyword detection or open-ended input. - grammY sessions for multi-step flows: Install
@grammyjs/conversationsand specify "use grammY conversations plugin" in CLAUDE.md for bots that need to ask questions and wait for responses. - Global error handler: Ask Claude Code to implement
bot.catch(err => console.error(err))with specific error types for API failures, timeouts, and user-generated edge cases.
For bots that need to trigger external workflows or integrate with other services, agentic workflows with Claude Code covers how Claude Code builds automated pipelines that bots can connect to.
How Do You Connect the Bot to External Services?
Most bots get their real value from external connections: databases, APIs, or third-party services. Keep all integration logic in dedicated service files outside of handler functions. Handlers should call services, not contain them.
Claude Code generates clean separation when the file structure is specified in CLAUDE.md. A src/lib/db.ts for database access and a src/services/ directory for external APIs gives Claude Code clear locations for each integration.
- Database integration: Install Prisma or a Supabase client and ask Claude Code to generate a database module in
src/lib/db.tsthat handler files import. No database logic inside handlers. - External API services: Create one service file per external API in
src/services/. Prompt Claude Code to write each as async functions that command handlers await directly. - All environment variables in CLAUDE.md: List every expected variable name so Claude Code references
process.env.STRIPE_API_KEYcorrectly across every file it generates. - Rate limiting for Telegram's API: Telegram allows 30 messages per second globally and 1 per second per chat. Ask Claude Code to add the grammY auto-retry plugin for bots that send multiple messages.
- Caching for stable external data: For API calls returning data that changes infrequently, ask Claude Code to add an in-memory cache or a Redis TTL cache with a specific duration in the prompt.
How Do You Deploy the Telegram Bot?
Railway and Fly.io are the two recommended deployment targets. Both handle Node.js automatically, both support environment secrets, and both give you the persistent process that a polling bot requires to stay running.
If you are using webhooks in production, confirm the webhook is registered after the first deploy by calling https://api.telegram.org/bot<token>/getWebhookInfo. A successful response confirms Telegram is delivering updates to your server.
- Railway deployment: Connect the GitHub repository to Railway, set
TELEGRAM_BOT_TOKENandWEBHOOK_URLas environment variables, and deploy. Railway detects Node.js and starts the process automatically. - Fly.io deployment: Run
fly launchfrom the project directory, add secrets withfly secrets set TELEGRAM_BOT_TOKEN=..., and deploy. Fly.io gives persistent containers with automatic restart on failure. - Webhook registration on first deploy: The bot calls
setWebhookon startup with the production URL. Verify registration withgetWebhookInfoafter the first successful deploy. - PM2 for VPS deployments: If deploying to a raw VPS, use
pm2 start dist/index.js --name mybotto keep the process alive across server reboots.
For connecting the bot to Claude Code's channel delivery features, Claude Code channel setup for Telegram covers the integration.
How Does Telegram Bot Development Compare to Other Bots?
Telegram is the easiest bot platform to deploy publicly. No OAuth app approval, no workspace restrictions, and no admin installation flow. Any user can start your bot immediately from a direct link.
The tradeoff is audience and context. Telegram reaches mass consumer audiences and privacy-focused users. Other platforms serve different use cases where their native integrations are more valuable than Telegram's deployment simplicity.
- Telegram vs Slack: Telegram deploys publicly with no approval process. For internal team tools with existing workspace integrations, building a Slack bot with Claude Code covers the Slack-specific approach.
- Telegram vs Discord: Discord is better for community management and gaming communities. Telegram is better for mass consumer audiences and privacy-focused users at scale.
- Telegram vs Chrome extensions: Telegram bots work across all devices without installation. For browser-level page access that bots cannot provide, see building a Chrome extension with Claude Code.
- When Telegram is the right choice: Messaging large user bases without app installs, delivering notifications, running surveys, providing customer support, or building for Telegram-native audiences.
- Bot vs app: Telegram bots are interfaces for single-purpose interactions. Complex multi-screen experiences warrant a dedicated web or mobile app instead.
Conclusion
Building a Telegram bot with Claude Code is straightforward when the setup is right.
grammY's patterns are consistent, the Bot API is clean, and Claude Code generates accurate handler code when the command structure is in CLAUDE.md before the first session starts. The two decisions that matter most are the bot's purpose, written as a single clear sentence, and the update method, chosen before any connection code is written.
Open BotFather, create the bot, and copy the token into .env. Write the CLAUDE.md with the purpose statement, the command list, and the library choice. That is everything Claude Code needs to start building the bot correctly from the first prompt.
Need a Telegram Bot Built to Production Standards?
Most bots stall between a working local prototype and a production deployment that handles real users reliably. The gap is usually external service integration, error handling, and a deployment setup that stays running without manual intervention.
At LowCode Agency, we are a strategic product team, not a dev shop. We build grammY-based Telegram bots with external API integrations, database connections, conversation flows, and production deployment that handles real traffic from day one.
- Bot architecture design: We scope the command structure, conversation flows, and external integrations before writing the first handler, so the build is clean from the start.
- grammY development: We build TypeScript-first bots with correct session management, error handling, and handler organisation that scales beyond the initial feature set.
- External API integration: We connect bots to databases, payment processors, CRMs, and third-party APIs using clean service layer patterns Claude Code can extend.
- Webhook configuration: We set up production webhook handling with Express integration, proper SSL configuration, and startup registration with Telegram's API.
- Production deployment: We deploy to Railway or Fly.io with environment secrets, automatic restarts, and the monitoring needed to know when the bot goes down.
- Rate limiting and reliability: We implement Telegram API rate limiting, retry logic, and graceful error handling so the bot stays online under real user load.
- Full product team: Strategy, design, development, and QA from a team experienced in AI bot development with LowCode Agency across 350+ production builds.
We have built 350+ products for clients including Coca-Cola, American Express, and Medtronic.
If you want a Telegram bot built to production standards and deployed correctly from the start, get in touch with the team.
Last updated on
April 10, 2026
.









