Build a Telegram Mini App with React & Python (2026 Guide)
In 2026, Telegram Mini Apps (TMAs) have emerged as one of the most explosive platforms for user acquisition, community engagement, and web3 integration. With over 950 million active users, the ability to launch a full-featured web application directly inside a chat window has revolutionized how developers deploy software. Tap-to-earn games, decentralized exchanges, and automated utility utilities no longer require users to navigate external app stores or install third-party plugins. However, building a production-grade Telegram Mini App requires a solid understanding of both frontend client SDKs and backend cryptographic signature verification. This comprehensive, step-by-step guide walks you through building a Telegram Mini App from scratch using a modern stack: React with Vite, Tailwind CSS, and a secure Python FastAPI backend.
To build a Telegram Mini App, create a bot via @BotFather, run the command /newapp, set up a React frontend utilizing the @telegram-apps/sdk-react library, and connect it to a Python FastAPI backend. The backend must cryptographically validate the initData string using your bot token. For a curated directory of developer tools, browse Telekit's Tech & AI Catalog.
Why Developers are Flocking to Telegram Mini Apps in 2026
The developer ecosystem has shifted dramatically toward decentralized, low-friction platforms. Telegram Mini Apps offer direct access to Telegram's native user interface, allowing developers to create experiences that feel integrated with the operating system. With tools like haptic feedback, custom theme color detection, and the native bottom action button (MainButton), a TMA provides a native application feel while running on standard web technologies.
Furthermore, security and payment capabilities have reached maturity in 2026. The introduction of Telegram Stars allows developers to charge for digital goods and services with global coverage, while the Telegram Gateway API provides cheap, instant phone-number verification. Building on this ecosystem enables developers to go from zero to thousands of users overnight without marketing hurdles.
Prerequisites and Local Development Environment Setup
Before writing code, ensure you have the following prerequisites installed on your development machine:
- Node.js (v18 or higher): Required to build and run the React frontend.
- Python (v3.10 or higher): Used for the secure FastAPI backend.
- ngrok: A secure tunneling tool to expose your local frontend and backend to the internet for live mobile testing.
- Telegram Desktop Client: Necessary to run and preview your Mini App during active coding.
Step 1: Creating Your Telegram Bot & App Entry Point
Every Telegram Mini App must be anchored to a parent Telegram Bot. To set this up, interact with Telegram's official bot builder, BotFather:
- Open Telegram and search for @BotFather.
- Send the command
/newbotand follow the prompts to name your bot and choose a unique username. - Save the generated HTTP API Bot Token securely. You will need this token for backend validation.
- Send the command
/newappto create the Mini App web interface. Select your bot, enter a title, and provide a short description. - When asked for the Web App URL, enter a temporary placeholder (e.g.,
https://example.com) or your live ngrok URL. We will update this later.
Step 2: Building the React Frontend with Vite & Tailwind CSS
We will use React, Vite, and Tailwind CSS to construct a responsive, mobile-first frontend. We also integrate the official @telegram-apps/sdk-react library to read user data and manage theme aesthetics.
Run the following commands in your terminal to initialize the React application:
# Initialize React app using Vite
npm create vite@latest tma-frontend -- --template react-ts
cd tma-frontend
# Install Tailwind CSS and its dependencies
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
# Install the official Telegram Apps SDK for React
npm install @telegram-apps/sdk-react
Next, configure your tailwind.config.js file to scan your React source files for utility classes:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Now, modify src/App.tsx to initialize the Telegram SDK and display the user's information along with an action button:
import React, { useEffect, useState } from 'react';
import { initMiniApp, initViewport, retrieveLaunchParams } from '@telegram-apps/sdk-react';
export default function App() {
const [userData, setUserData] = useState<any>(null);
const [initDataRaw, setInitDataRaw] = useState<string>('');
useEffect(() => {
try {
// Initialize the SDK component configurations
const [miniApp] = initMiniApp();
initViewport();
// Notify Telegram that the app is ready to display
miniApp.ready();
// Retrieve launch parameters passed by Telegram client
const launchParams = retrieveLaunchParams();
setInitDataRaw(launchParams.initDataRaw || '');
setUserData(launchParams.initData?.user || null);
} catch (error) {
console.error("SDK Initialization failed", error);
}
}, []);
const sendDataToBackend = async () => {
try {
const response = await fetch('https://your-backend.ngrok.app/api/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData: initDataRaw }),
});
const data = await response.json();
alert(`Backend verification response: ${JSON.stringify(data)}`);
} catch (err) {
console.error(err);
alert('Error connecting to backend!');
}
};
return (
<div className="min-h-screen bg-slate-900 text-white flex flex-col items-center justify-center p-6">
<div className="max-w-md w-full bg-slate-800 rounded-2xl shadow-xl border border-slate-700 p-6 space-y-6 text-center">
<h1 className="text-2xl font-bold text-sky-400">Telegram Mini App</h1>
{userData ? (
<div className="space-y-3">
<p className="text-lg">Welcome, <span className="font-semibold text-emerald-400">@{userData.username}</span>!</p>
<div className="text-sm text-slate-400 bg-slate-950 p-4 rounded-lg text-left overflow-auto max-h-32">
<pre>{JSON.stringify(userData, null, 2)}</pre>
</div>
</div>
) : (
<p className="text-rose-400">Unable to load Telegram user context.</p>
)}
<button
onClick={sendDataToBackend}
className="w-full bg-sky-500 hover:bg-sky-600 transition-colors text-white font-bold py-3 px-6 rounded-xl shadow-lg shadow-sky-500/20"
>
Verify Session with Backend
</button>
</div>
</div>
);
}
Step 3: Setting Up the Secure Python FastAPI Backend
When a user opens your Mini App, the frontend receives a query string called initDataRaw. The client-side data can be easily intercepted or faked. Therefore, your backend must cryptographically validate this data before executing any state changes or database mutations. Telegram signs this string using an HMAC-SHA256 signature generated from your bot's token.
Create a directory named tma-backend, initialize a virtual environment, and install dependencies:
mkdir tma-backend
cd tma-backend
python -m venv venv
source venv/Scripts/activate # On Windows: venv\Scripts\activate
# Install FastAPI, Uvicorn, and standard cryptographic packages
pip install fastapi uvicorn cryptography requests pydantic
Write the backend server code in a file named main.py. This script parses the query string, generates a secret key using your bot token, and compares the signature:
import hmac
import hashlib
from urllib.parse import parse_qsl
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = FastAPI()
# Enable CORS for local testing from Vite frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
BOT_TOKEN = "YOUR_BOT_TOKEN_HERE" # Replace with your real token from @BotFather
class InitDataPayload(BaseModel):
initData: str
def validate_telegram_data(init_data: str, bot_token: str) -> dict:
"""Validate Telegram query parameters against the bot token."""
try:
# Parse the raw initData query string into key-value pairs
parsed_data = dict(parse_qsl(init_data))
if "hash" not in parsed_data:
raise ValueError("Missing hash parameter.")
received_hash = parsed_data.pop("hash")
# Sort and concatenate all parameters chronologically
data_check_string = "\n".join(f"{k}={v}" for k, v in sorted(parsed_data.items()))
# Telegram Web App cryptographic validation algorithm
secret_key = hmac.new(b"WebappData", bot_token.encode(), hashlib.sha256).digest()
calculated_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest()
# Secure string comparison to avoid timing attacks
if not hmac.compare_digest(calculated_hash, received_hash):
raise ValueError("Cryptographic hash mismatch.")
return parsed_data
except Exception as e:
raise HTTPException(status_code=400, detail=f"Authentication failed: {str(e)}")
@app.post("/api/validate")
async def validate_session(payload: InitDataPayload):
parsed_user_data = validate_telegram_data(payload.initData, BOT_TOKEN)
return {"status": "success", "user": parsed_user_data}
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
Step 4: Exposing Your Local Server via ngrok
Telegram client apps load Web App content inside secure IFrames requiring HTTPS. During local development, your browser or mobile client will block standard unencrypted HTTP links. We solve this by using ngrok to build a secure HTTPS tunnel to your local machine.
Open two separate terminal windows and run the following commands to tunnel both the React frontend and FastAPI backend:
# In Terminal 1 (tunneling React frontend - Vite default port 5173)
ngrok http 5173
# In Terminal 2 (tunneling FastAPI backend - default port 8000)
ngrok http 8000
Copy the generated HTTPS URLs provided by ngrok (e.g., https://a1b2-cd34.ngrok-free.app). Update the API fetch URL in your React code with the backend ngrok link, then update your App configuration in BotFather with the frontend ngrok link.
Security Best Practices for Telegram Mini App Production
When migrating your application from local testing to a production server, maintain these critical security measures:
Frequently Asked Questions (FAQ)
Why am I getting "Invalid Signature" on the backend?
Double-check that the bot token you are using matches the exact token issued by @BotFather. Furthermore, ensure you are passing the raw query string (initDataRaw) and not the pre-decoded JSON object from the SDK, as any modification to formatting changes the cryptographic output.
Can I test my Telegram Mini App in local browser environments?
Yes. You can mock the Telegram launch environment during local styling using standard web mocking methods. The React SDK provides a mock mode to prevent crash events when Telegram APIs are not present in global window frames.
How do I implement custom theme themes?
The React SDK detects the client's current color palette automatically (e.g. background color, text color, link color). You can read these properties and map them directly to Tailwind CSS custom color classes or root CSS custom properties to ensure your app matches Telegram's appearance.
Are Telegram Mini Apps free to host?
Yes. Hosting the Mini App is identical to hosting any static website and server API. You can host the React frontend on free static hosting solutions (like Vercel, Netlify, or GitHub Pages) and deploy the FastAPI backend to VPS platforms.
Conclusion
Building a Telegram Mini App bridges the gap between clean web development and native mobile reach. Using React and Python, you can quickly build user-centric dashboards, interactive utilities, and game economies that deploy in seconds. Always prioritize backend signature validation and protect your secrets in production. Dive in, start building, and take advantage of the massive Telegram user base today!
No active reviews. Be the first to add one!