Skip to content

Instantly share code, notes, and snippets.

@Malith-Rukshan
Last active April 22, 2025 02:36
Show Gist options
  • Save Malith-Rukshan/da02bbf6e0219653c53ec9116cdd37f2 to your computer and use it in GitHub Desktop.
Save Malith-Rukshan/da02bbf6e0219653c53ec9116cdd37f2 to your computer and use it in GitHub Desktop.
Validate Init data of Telegram Mini-App | TypeScript & Python
import hmac
def checkValidateInitData(hash_str, init_data, token, c_str="WebAppData"):
"""
Validates the data received from the Telegram web app, using the
method documented here:
https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app
hash_str - the has string passed by the webapp
init_data - the query string passed by the webapp
token - Telegram bot's token
c_str - constant string (default = "WebAppData")
"""
init_data = sorted([ chunk.split("=")
for chunk in unquote(init_data).split("&")
if chunk[:len("hash=")]!="hash="],
key=lambda x: x[0])
init_data = "\n".join([f"{rec[0]}={rec[1]}" for rec in init_data])
secret_key = hmac.new(c_str.encode(), token.encode(),
hashlib.sha256 ).digest()
data_check = hmac.new( secret_key, init_data.encode(),
hashlib.sha256)
return data_check.hexdigest() == hash_str
import crypto from 'crypto';
/**
* Validates the data received from the Telegram web app, following the
* documentation: https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app
*
* @param hashStr - The hash string passed by the web app.
* @param initData - The query string passed by the web app.
* @param token - Telegram bot's token.
* @param cStr - Constant string (default = "WebAppData").
* @returns Boolean indicating whether the validation is successful.
*/
export async function checkValidateInitData(hashStr: string, initData: string, token: string, cStr = 'WebAppData'): Promise<boolean> {
// Parse and sort the init data
const sortedData = initData
.split('&')
.filter(chunk => !chunk.startsWith('hash='))
.map(chunk => chunk.split('='))
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
.join('\n');
// Create secret key
const secretKey = new Uint8Array(crypto.createHmac('sha256', cStr)
.update(token)
.digest());
// Generate the data check hash
const dataCheck = crypto.createHmac('sha256', new Uint8Array(secretKey))
.update(sortedData)
.digest('hex');
// Compare the generated hash with the provided hash
return dataCheck === hashStr;
}
@Quatry
Copy link

Quatry commented Dec 21, 2024

helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment