npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

telegram-reader

v1.4.0

Published

Read Telegram channel posts via MTProto as flat rows with text and lightweight photo previews — built for LLM agents, analytics, and trading-signal backtests with backtest-kit

Readme

telegram-reader

A library for reading posts from Telegram channels via MTProto (a userbot built on gramjs). It returns channel messages as flat rows with text and a lightweight photo preview — a convenient format for feeding an LLM agent, analytics, or a trading-signal backtest.

Features

  • QR-code authorization — one interactive session, after which the client reuses the saved session.txt.
  • Three fetch modes:
    • scrapeDay — all posts of a calendar day (UTC);
    • scrapeLookback — a sliding "last N minutes/hours/days" window free of look-ahead bias, suitable for both backtesting and live mode;
    • scrapePage — classic limit/offset pagination deep into the channel history.
  • Photo previews: the image is downloaded in full size, rotated according to EXIF, and compressed to a JPEG 800px wide (quality 80) via sharp; it lands in the row as base64. Downloads go through a pool (maxExec: 5) to avoid OOM on weak hardware.
  • Posts with neither text nor photo are skipped; the result is always ordered newest-first.

Installation and build

npm install
npm run build   # rollup → build/index.cjs, build/index.mjs + types.d.ts

Requires Node.js (sharp and fs/promises are used).

Setup

  1. Get an api_id and api_hash at my.telegram.org and pass them via setConfig before the first call to any other function (recommended way):

    import { setConfig } from "telegram-reader";
    
    setConfig({
      CC_TELEGRAM_API_ID: 1234567,
      CC_TELEGRAM_API_HASH: "0123456789abcdef0123456789abcdef",
    });

    Values set through setConfig take priority over everything else. Alternatively, use environment variables (a .env file works too):

    CC_TELEGRAM_API_ID=1234567
    CC_TELEGRAM_API_HASH=0123456789abcdef0123456789abcdef

    Resolution order: setConfig → environment variables → built-in defaults. The current effective values can be inspected with getConfig().

  2. Create session.txt by signing in once. The recommended way is a one-liner:

    node -e 'require("telegram-reader").signIn()'

    Or call it from your own code:

    import { signIn } from "telegram-reader";
    
    await signIn();
    // Session saved to ./session.txt

    A QR code appears in the console — scan it in Telegram (Settings → Devices → Link Desktop Device); if 2FA is enabled, you will be prompted for the password. The session is saved to ./session.txt and reused by all subsequent calls.

Usage

Each result row has the following shape:

interface ScraperMessage {
  id: number;          // message id within the channel
  channel: string;     // channel exactly as passed in the request
  content: string;     // post text ("" if photo-only)
  date: Date;          // publication time
  photo: string | null; // base64 JPEG preview or null
}

All posts of a day

import { scrapeDay } from "telegram-reader";

const rows = await scrapeDay({
  channel: "some_channel",
  when: new Date("2026-09-19"), // only the UTC date part matters
});

scrapeDay covers the whole day, including posts published after when — in a backtest that is look-ahead bias. Use scrapeLookback for backtesting.

Sliding window (no look-ahead bias)

import { scrapeLookback } from "telegram-reader";

// the last 6 hours relative to the "current moment"
const rows = await scrapeLookback({
  channel: "some_channel",
  when: new Date(),   // in a backtest — the simulated "now"
  limit: 6,
  dimension: "hour",  // "minute" | "hour" | "day", defaults to "minute"
});

The window is [when - limit * dimension, when): a post dated exactly when or later never makes it into the result — at that moment it is not yet "visible".

Paging through history

import { scrapePage } from "telegram-reader";

const when = new Date(); // pin the boundary so pages don't drift
const page1 = await scrapePage({ channel: "some_channel", when, limit: 20, offset: 0 });
const page2 = await scrapePage({ channel: "some_channel", when, limit: 20, offset: 20 });

Direct client access

import { getTelegram } from "telegram-reader";

const client = await getTelegram(); // authorized TelegramClient (singleton)

REPL

npm run repl

Builds the project and starts Node with .env loaded — handy for testing the functions by hand.