Skip to content
TGWAY
Channels & Bots STEP 75 / 99

Verify Telegram Mini App Users: Check the initData Signature

Never trust initDataUnsafe. Check the initData hash with an HMAC of your bot token, reject old auth_date values, and handle mini apps opened without initData.

  • Applies toDevelopers
  • LevelL4
  • Reading time4 min
  • Verified

The short answer

  1. 1User data a mini app receives cannot be trusted until its signature is checked.
  2. 2Send initData to your server, sort the pairs, compare the hash using a WebAppData key.
  3. 3Reject stale auth_date values and empty initData.
In this article
  1. Why you must check it
  2. Verify it with your bot token
  3. Verifying without the token, for third parties
  4. Depending on how it opened, initData may be empty
  5. FAQ
  6. At a glance

Why you must check it

When a mini app opens, Telegram passes the web page details about the user who opened it. That data lives in the browser on the user's device, so anyone who wants to can change it before it reaches your server. Your server should trust the user only after checking Telegram's signature, especially for anything involving money or accounts: awarding points, taking orders, logging in.

ValueWhat it isUse it for
initDataThe raw string, signature includedSend it to your server and verify it there
initDataUnsafeThe same data already parsed into an objectOnly for showing a name on screen; never trust it

Verify it with your bot token

  1. The mini app sends the Telegram.WebApp.initData string to your server unchanged.
  2. Your server splits it into key=value pairs and sets hash aside.
  3. Sort the remaining pairs by key name and join them with newline characters. This is the data-check string.
  4. The secret key is the HMAC-SHA256 of your bot token, using the fixed key WebAppData.
  5. If the HMAC-SHA256 of the data-check string with that secret key, in hex, equals the hash you set aside, Telegram produced the data.
  6. Reject it if auth_date, the time it was created, is too old. This stops someone replaying data they stole earlier.
import hmac, hashlib, time
from urllib.parse import parse_qsl

def check(init_data, bot_token, max_age=3600):
    pairs = dict(parse_qsl(init_data))
    received = pairs.pop("hash", "")
    text = chr(10).join(f"{k}={v}" for k, v in sorted(pairs.items()))  # newline-joined
    secret = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()
    ok = hmac.compare_digest(
        hmac.new(secret, text.encode(), hashlib.sha256).hexdigest(), received)
    return ok and time.time() - int(pairs.get("auth_date", 0)) < max_age

This is a minimal example using only Python's standard library. Choose max_age to suit your service.

Verifying without the token, for third parties

When a service other than your own server needs to confirm the user, initData also carries a signature field, an Ed25519 signature. It is checked with a public key that Telegram publishes, so you never hand over your bot token. The data-check string is built slightly differently, with the bot ID added at the start, so follow the official procedure exactly if you use this method.

Depending on how it opened, initData may be empty

Where the mini app was opened frominitData
Inline button, menu button, main mini app, direct link, attachment menuPresent
Reply keyboard button, inline modeAbsent. An app opened from a reply keyboard returns up to 4096 bytes to the bot with sendData instead

If initData is empty, treat the user as unknown. Letting an empty value through is the most common mistake.

To open a mini app from the menu button, see the bot menu button. To log users in on a website outside Telegram, see Log in with Telegram.

FAQ

How do I validate Telegram mini app initData?

On your server, remove hash, sort the other fields, join them with newlines, and compare the HMAC-SHA256 using a secret derived from your bot token with the key WebAppData.

Can I trust initDataUnsafe?

No. It is unverified data from the browser; use it only for display.

Why is initData empty in my mini app?

Mini apps opened from a reply keyboard button or inline mode do not receive initData.

Sources

Summary

At a glance

Verify Telegram Mini App Users: Check the initData Signature — at a glance illustration
  1. 1Trust

    initDataUnsafe is for display only.

  2. 2Check

    HMAC-SHA256 with a key derived from the bot token; constant-time compare.

  3. 3Edge cases

    Old auth_date and empty initData are rejected.

Share this guide

Send it to a friend who has the same question.

Telegram WhatsApp
More

Open on your phonePoint your phone camera here to open this guide.

Updated

Related articles

View all ›