GramFlow
GramFlow uses your own Telegram account to upload files up to 4 GiB (2 GiB on non-Premium accounts) straight from the terminal — no bot, no Saved Messages gymnastics, no browser upload limits.
It started as a maintenance-focused fork of the unmaintained
uploadgram project, migrated to
an actively maintained Telegram client library, and picked up a long list of
bug fixes along the way.
- Heavily inspired by telegram-upload
Features
- Uploads any file or a whole directory tree (recursively) to a chat, group, channel, or forum topic
- Sends images as real Telegram photos, videos as videos (with an auto-generated thumbnail), audio with proper metadata — everything else as a document
- Groups consecutive photos/videos into Telegram albums (media groups) instead of one message per file
- Resumes an interrupted batch — re-running the same folder against the same destination skips files already uploaded
- Batch-wide progress in a single status message, alongside the existing per-file progress bar
gramflow login/gramflow logoutto manage the saved session explicitly- Optional delete-on-success, custom captions, custom thumbnails, and a live console progress bar
- Skips oversized files with a clear notice instead of failing silently
- Natural file ordering (
file2beforefile10) and dotfiles ignored
Installation
pip install gramflow
Requirements
- Python 3.10+
ffmpegon yourPATH(optional — only needed to auto-generate video thumbnails; uploads still work without it)kurigram— installed automatically as a dependency. It's an actively maintained drop-in replacement forpyrogram, and is still imported aspyrogramin code, per its own convention.
On first run, GramFlow will ask for a Telegram api_id and api_hash. Get
both for free at my.telegram.org (API development
tools) and they'll be saved to ~/.config/gramflow/config.env for future
runs.
Usage
Authentication
gramflow login # authenticate once and save the session
gramflow logout # revoke the session with Telegram and remove it locally
You don't need to run login explicitly — the first upload will prompt for
phone number / code / 2FA password automatically if there's no saved
session. login/logout exist as explicit, discoverable commands for
managing that session on demand (e.g. switching accounts, or fully logging
out of a shared machine).
Uploading
gramflow <chat_id> <path> [options]
$ gramflow 7351948 /path/to/dir/or/file --delete_on_success --fd -t /path/to/custom/thumbnail --caption "A Custom Caption" --topic 1
| Argument | Description |
|---|---|
chat_id |
Destination chat: numeric id, -100... channel/supergroup id, legacy - group id, or @username |
dir_path |
File or directory to upload |
--delete_on_success |
Delete each file locally after it uploads successfully |
--fd |
Force every file to be sent as a plain document |
--t <path> |
Custom thumbnail to use for videos |
--caption "text" |
Caption applied to every uploaded file (default: no caption) |
--progress |
Show a live progress bar in the terminal |
--topic <id> |
Forum topic id to upload into |
--no-resume |
Don't skip previously uploaded files for this folder/destination |
--fresh |
Clear saved resume progress for this folder/destination first |
--no-albums |
Send every photo/video as its own message instead of grouping into albums |
The boolean flags (--delete_on_success, --fd, --progress, --no-resume,
--fresh, --no-albums) are plain on/off switches — include the flag to
enable it, omit it to disable it. --delete_on_success True does not
work; just pass --delete_on_success on its own.
By default, files are sent without a caption. To get the old
file-name-as-caption behaviour back, pass --caption "<filename>" yourself.
Resuming an interrupted upload
If a batch is interrupted (crash, Ctrl+C, lost connection), just run the
exact same command again — files already confirmed uploaded (matched by
path, size, and modified time) are skipped automatically, and the batch
picks up where it left off. Pass --fresh if you want to force a full
re-upload of that same folder/destination instead.
Configuration
Environment variables (all optional besides the two credentials, which will be prompted for interactively if missing):
| Variable | Purpose | Default |
|---|---|---|
GF_TG_APP_ID |
Telegram api_id |
— |
GF_TG_API_HASH |
Telegram api_hash |
— |
GF_TG_ST |
sleep_threshold passed to the client |
10 |
GF_TG_WS |
Number of worker threads | 10 |
GF_TG_MCTS |
Max concurrent transmissions | 4 |
GF_TG_MMC |
Max message cache size | 10000 |
GF_TG_MBUC |
Max business-user-connection cache size | 200 |
Security note
GramFlow logs in as your own Telegram account, not a bot. The session
file it creates under ~/.config/gramflow/ grants full access to that
account — treat it like a password (don't commit it, don't share it, don't
upload it anywhere). Automating a personal account also falls under
Telegram's own Terms of Service for user accounts, so keep usage reasonable
(avoid extremely high message/upload rates) to stay within normal limits.
Troubleshooting
FLOOD_WAIT_Xerrors — Telegram is rate-limiting your account; wait the number of seconds it reports before retrying. Sending very large batches back-to-back makes this more likely.- Album upload fails — GramFlow does not automatically retry a failed media-group request as individual messages. This is intentional: after a network timeout, Telegram may have accepted the album even if the client did not receive the response, and an automatic fallback could duplicate the files. The failed files are retained in resume state for an explicit retry.
- No video thumbnail generated — make sure
ffmpegis installed and on yourPATH. Without it, uploads still work, just without a thumbnail. - Asked for
api_id/api_hashevery run — check that~/.config/gramflow/config.envis writable and isn't being wiped by another process (e.g. a container that resets$HOMEon restart). - Asked to log in again unexpectedly — the session file lives at
~/.config/gramflow/GramFlow.session. If it's missing or was deleted, the next upload (orgramflow login) will re-prompt for authentication. - A file re-uploads even though it succeeded before — resume matching
is based on path, size, and modified time; if any of those changed (e.g.
the file was re-saved or moved), it's treated as a new file. Use
--freshto intentionally clear resume history for a folder.
Contributing
Issues and pull requests are welcome at github.com/kavidu-dilhara/gramflow.
License
MIT License — see LICENSE. GramFlow is a fork of
uploadgram; original copyright is preserved in file headers alongside the
new copyright for this fork.
Author
Kavidu Dilhara GitHub: @kavidu-dilhara Repository: github.com/kavidu-dilhara/gramflow
Metadata
Release files for gramflow 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gramflow-1.0.2.tar.gz | 36.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gramflow-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.9 kB
Release files / gramflow-1.0.2.tar.gz
| Download URL | gramflow-1.0.2.tar.gz |
|---|---|
| Size | 36.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
67659ca2a6a82792eacaec4a66e4128efae8c70888035935ab7996df535649b1
|
|
BLAKE2b-256 checksum How to use checksums |
e1aa9faa4877d8187a7ccb4d4deaea4670666985805d4db83d9e7c2fb8d4c241
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.3 CPython/3.12.14 Linux/6.17.0-1022-azure
|
Release files / gramflow-1.0.2-py3-none-any.whl
| Download URL | gramflow-1.0.2-py3-none-any.whl |
|---|---|
| Size | 41.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
19cd59a81f3bf03d059ade2645186d50ffba85c1c6fe4d1daea57484be3edef0
|
|
BLAKE2b-256 checksum How to use checksums |
4b45f08c8d9b9b7a446275c791a3d953a884bc15862b0db7a6d63a51e88f414e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.3 CPython/3.12.14 Linux/6.17.0-1022-azure
|