Most "Telegram scraping in Python" tutorials tell you to install Telethon, register an API ID with your phone number, and log in as a user bot. Fine — until you're monitoring 200 public channels and your collection dies the day Telegram bans the session, rate-limits the account, or the phone that owns the number changes SIMs.
For public channels, you don't need an account at all. The web preview at t.me/s/<channel> returns the last ~20 posts as plain HTML. Scrape that, and your "API" is a GET request with zero credentials.
The shape of a collector that survives
import requests, re, json, time, random
from pathlib import Path
CH = Path("channels.txt").read_text().split()
seen = json.loads(Path("seen.json").read_text()) if Path("seen.json").exists() else {}
raw = Path("raw"); raw.mkdir(exist_ok=True)
for ch in CH:
r = requests.get(f"https://t.me/s/{ch}", timeout=15,
headers={"User-Agent": "Mozilla/5.0"})
if r.status_code != 200:
continue # degrade: miss, don't crash
html = r.text
(raw / f"{ch}-{int(time.time())}.html").write_text(html)
ids = re.findall(r'data-post="[^"]*-(\d+)"', html)
new = [i for i in ids if i not in set(seen.get(ch, []))]
seen.setdefault(ch, []).extend(new)
time.sleep(3 + random.random() * 4) # jitter between channels
json.dump(seen, open("seen.json", "w"))
The four rules that separate a toy from a collector
- Store raw first, parse later. Raw HTML per fetch, timestamped on disk. Parsers improve; raw never changes. Re-parse free, re-fetch forever.
-
IDs, not text.
data-postIDs are per-channel and sequential. Diff on IDs and you get exact new-post detection; diff on text and you get duplicate nightmares. -
Persist
seen. In-memory dedupe resets on every restart — which is exactly when collectors restart. - Degrade, don't crash. A 429, a 503, a network blip: skip the cycle, catch up against the preview window. Unattended means the loop assumes it will be punched.
When you do want the real API
Private channels, media downloads at scale, posting, search — that's Telethon/MTProto territory, with account risk attached. Public monitoring is a solved problem at the preview layer; pay the account-risk tax only for capabilities you actually use.
I run the pattern above across ~200 channels for market and OSINT signals. The playbook — cadence design, ?before= cursor paging for backfill, repost-ring flags, wording-diff alerting — is the $5 bundle: https://heyuhe.gumroad.com/l/poddr. Free sample brief, pay what you want, $0 fine: https://heyuhe.gumroad.com/l/ruldgm.
Top comments (0)