TelePress
TelePress publishes Markdown, plain text, images, and ZIP galleries to Telegraph. It supports automatic pagination, external image hosts, image compression, concurrent uploads, and an optional REST API.
Requirements
- Python 3.10 or newer
- A Telegraph token, or permission to create one on first use
- An image-host configuration only when publishing images or galleries
Installation
pip install telepress
# Optional REST API
pip install "telepress[api]"
# Optional S3-compatible hosts such as AWS S3 and Cloudflare R2
pip install "telepress[s3]"
# Optional YAML configuration files
pip install "telepress[yaml]"
Install from source for development:
git clone https://github.com/redtidev1918/telepress.git
cd telepress
python -m pip install --editable ".[dev]"
Quick start
Publish a document:
telepress article.md --title "My post"
# The explicit subcommand is equivalent
telepress publish article.md --title "My post"
Publish an image or ZIP gallery after configuring an image host:
telepress configure
telepress check
telepress photo.jpg --title "Photo"
telepress gallery.zip --title "Gallery"
Useful publishing options:
# Override the configured image limit in MiB
telepress gallery.zip --image-size-limit 10
# Keep original images instead of compressing oversized files
telepress gallery.zip --no-compress
# Use a Telegraph-compatible API endpoint
telepress article.md --api-url http://localhost:9009
Text-only publishing does not load or require an image-host configuration.
The Telegraph access token is created automatically when needed and stored in
~/.telegraph_token unless one is supplied with --token.
REST API
Install the optional API dependencies first: pip install "telepress[api]".
telepress-server --host 127.0.0.1 --port 8000
Interactive OpenAPI documentation is available at
http://127.0.0.1:8000/docs.
curl -X POST http://127.0.0.1:8000/publish/text \
-H "Content-Type: application/json" \
-d '{"content":"# Title\n\nBody","title":"Example"}'
curl -X POST http://127.0.0.1:8000/publish/file \
-F "file=@article.md" \
-F "title=Example"
curl -X POST http://127.0.0.1:8000/publish/gallery \
-F "files=@p0.jpg" \
-F "files=@p1.jpg" \
-F "title=Gallery title" \
-F "tags=pixiv, illustration" \
-F "link=https://www.pixiv.net/artworks/123456" \
-F "spoiler=true"
/publish/gallery accepts repeated files parts plus optional title,
tags (comma-separated), link (source URL) and spoiler (truthy for R-18
content) form fields. Files are packed into a zip in upload order and
published with automatic pagination and Prev/Next navigation; tags, link
and the R-18 warning are rendered as a footer on the first page. It returns
{"ok": true, "url": "...", "files": N} and is compatible with generic
multipart delivery clients, e.g. PixivFlow httpMultipart targets pointing
at http://<telepress-host>:8000/publish/gallery.
Blocking file, compression, and network work is dispatched away from the API event loop, so concurrent requests do not serialize on those operations.
Image hosts
Supported hosts:
- ImgBB
- Imgur
- sm.ms
- S3-compatible storage, including AWS S3, Cloudflare R2, OSS, and MinIO
- Rclone remotes
- Custom HTTP upload APIs
Run telepress configure for the interactive setup, or create
~/.telepress.json:
{
"image_host": {
"type": "rclone",
"remote_path": "myremote:bucket/path",
"public_url": "https://cdn.example.com/path",
"rclone_flags": ["--transfers=32", "--checkers=32"],
"max_size_mb": 20,
"max_workers": 8
}
}
S3-compatible configuration:
{
"image_host": {
"type": "s3",
"access_key_id": "your-access-key",
"secret_access_key": "your-secret-key",
"bucket": "your-bucket",
"public_url": "https://cdn.example.com",
"endpoint_url": "https://s3.example.com",
"region_name": "auto"
}
}
Environment variables override file configuration:
export TELEPRESS_IMAGE_HOST_TYPE=imgbb
export TELEPRESS_IMAGE_HOST_API_KEY=your-key
Configuration is searched in the following locations:
- The path passed to
load_config() TELEPRESS_CONFIG~/.telepress.json,~/.telepress.yaml,~/.telepress.yml~/.config/telepress.json
Python API
from telepress import TelegraphPublisher, publish, publish_text
url = publish("article.md", title="My article")
text_url = publish_text("# Hello\n\nWorld", title="Hello")
publisher = TelegraphPublisher(image_size_limit=10)
gallery_url = publisher.publish("gallery.zip", title="Gallery")
Upload images directly:
from telepress import ImageUploader
uploader = ImageUploader("imgbb", api_key="your-key")
url = uploader.upload("photo.jpg")
batch = uploader.upload_batch(["1.jpg", "2.jpg"])
print(batch.success_rate, batch.get_url_map())
Behavior and limits
- Markdown and plain text are converted to Telegraph DOM nodes.
- Plain text chapter headings such as
Chapter 1and第一章are detected. - Large text is split near 10,000-character boundaries and linked with previous/next navigation.
- Galleries are split at 100 images per page.
- Images larger than 5 MiB are compressed by default; GIF compression is intentionally skipped.
- A 2 GiB input safety limit is applied before processing.
- Duplicate text publications are cached in
~/.telepress_cache.jsonby default.
Supported input extensions include .txt, .md, .markdown, .rst,
.text, .jpg, .jpeg, .png, .gif, .webp, .bmp, and .zip.
Error handling
from telepress import TelePressError, ValidationError, publish
try:
url = publish("article.md")
except ValidationError as exc:
print(f"Invalid input: {exc}")
except TelePressError as exc:
print(f"Publishing failed: {exc}")
Development and releases
python -m pip install --editable ".[dev]"
python -m pytest --cov
python -m build
python -m twine check dist/*
See CONTRIBUTING.md for contribution conventions and docs/RELEASING.md for the automated release workflow. Notable changes are recorded in CHANGELOG.md.
License
Release files for telepress 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| telepress-0.6.0.tar.gz | 70.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| telepress-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 109.4 kB
Release files / telepress-0.6.0.tar.gz
| Download URL | telepress-0.6.0.tar.gz |
|---|---|
| Size | 70.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b1d9c8f910a25dd0f9417d5606518cb85ed75dcf632ab12ce814266b27b2f59d
|
|
BLAKE2b-256 checksum How to use checksums |
cb5af28cb67b751bad5b3b5cd7b81e67cb9473cd857efe96c57859dcb7a077cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / telepress-0.6.0-py3-none-any.whl
| Download URL | telepress-0.6.0-py3-none-any.whl |
|---|---|
| Size | 38.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b8a73187e89fcff6b4892bbcecd9f5de2fe5435535dc8c1773574b6b12b4747b
|
|
BLAKE2b-256 checksum How to use checksums |
ad2b498e81e477173c142e2c493dedd99cd97538a650c26c64f1d27c8ee625d0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log