Skip to main content

Python Substack

Write Substack posts in Markdown and safely create, inspect, schedule, and publish them through Python, a command-line interface, or MCP.

PyPI Python Tests Release License Downloads

Documentation · Getting started · PyPI

From Markdown to a Substack draft

Install the package:

pip install python-substack

Check the selected account and publication:

substack status

Create a safe unpublished draft, then publish only when it is ready:

substack drafts create post.md
substack drafts publish 12345 --no-send

Publishing and deletion require confirmation. Noninteractive and JSON workflows must pass --yes explicitly.

Markdown source:

Markdown before conversion

Substack result:

Substack after conversion

What it supports

  • Create rich Substack drafts from Markdown.
  • Upload local images referenced by Markdown.
  • Set audience, comment permissions, SEO metadata, slug, sections, and tags.
  • List and inspect publications and drafts.
  • Export drafts to loss-aware Markdown backups without server writes.
  • Schedule, unschedule, publish, and delete drafts with explicit safeguards.
  • Use stable JSON envelopes in scripts and automation.
  • Authenticate with browser cookies or email and password.
  • Use the same publishing workflow from Python or an optional MCP server.

Setup

Copy .env.example to .env and configure one authentication method:

EMAIL=
PASSWORD=
PUBLICATION_URL=
COOKIES_PATH=
COOKIES_STRING=

Cookie authentication is usually more reliable when Substack requires captcha or magic-link sign-in. See Authentication for cookie export instructions and account-selection details.

Verify the installation without authenticating:

substack --version
substack --help

CLI

Create a draft with metadata:

substack --json drafts create post.md \
  --title "My Post" \
  --subtitle "Optional subtitle" \
  --tag python \
  --tag substack \
  --slug my-post \
  --search-engine-title "SEO title" \
  --search-engine-description "SEO description"

Inspect publications and drafts:

substack publications list
substack drafts list --limit 10
substack drafts get 12345
substack drafts export 12345 --output backup.md
substack --publication-url https://example.substack.com drafts list

Manage scheduling:

substack drafts schedule 12345 --at 2026-08-01T09:00:00+03:00
substack drafts unschedule 12345

Publish or delete intentionally:

substack drafts publish 12345 --no-send
substack drafts delete 12345 --yes

Global options such as --json, --cookies, and --publication-url must appear before the command:

substack --json drafts list
substack --cookies cookies.json --json status

The original standalone commands remain supported. See Legacy CLI commands.

Python

import os

from dotenv import load_dotenv
from substack import Api

load_dotenv()

api = Api(
    email=os.getenv("EMAIL"),
    password=os.getenv("PASSWORD"),
    publication_url=os.getenv("PUBLICATION_URL"),
)

result = api.create_draft_from_markdown(
    title="Shipping with Python",
    subtitle="A short note from a script",
    markdown="""
# Hello

This draft was created from **Markdown**.

![Alt text](https://example.com/image.png "Image caption")
""",
    tags=["python", "automation"],
    slug="shipping-with-python",
)

print(result["draft"]["id"])

create_draft_from_markdown creates a draft by default. It publishes only when publish=True is passed.

Back up an existing draft without modifying it:

backup = api.export_draft_to_markdown(12345)
print(backup["markdown"])
print(backup["unsupported_nodes"])

For direct ProseMirror node construction, see the low-level Python API. YAML workflows are documented in YAML drafts.

Markdown

Supported Markdown includes headings, paragraphs, bold, italic, inline code, strikethrough, superscript, subscript, links, images, linked images, image captions, code blocks, blockquotes, ordered and unordered lists, horizontal rules, footnotes, LaTeX math, pull quotes, and callouts.

from substack.post import Post

post = Post("Title", "Subtitle", user_id=1)
post.from_markdown(
    """
# Heading

Paragraph with **bold**, *italic*, `code`, and [links](https://example.com).
"""
)

Pass api= to upload local images while rendering:

post.from_markdown(markdown_content, api=api)

See the complete Markdown reference.

MCP

Install and run the optional MCP server:

pip install "python-substack[mcp]"
substack-mcp

The MCP tools use the same environment variables and SDK behavior as the CLI. See MCP server for the tool list and safety notes.

Project documentation

Compatibility

The project preserves existing Python APIs, console commands, CLI behavior, environment variables, JSON keys, and MCP tool signatures through the 1.x series. Additive capabilities may be introduced. See the compatibility policy.

Disclaimer

This project is not affiliated with Substack. It uses undocumented Substack interfaces that may change without notice.

Release files for python-substack 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-substack 0.8.0
File Size Uploaded
python_substack-0.8.0.tar.gz 33.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for python-substack 0.8.0
File Interpreter ABI Platform
python_substack-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.2 kB

Release files / python_substack-0.8.0.tar.gz

Download URL python_substack-0.8.0.tar.gz
Size 33.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1f3c321952ce93897743cdbc04157619e1d683f8e118263495d21d11868e9cde
BLAKE2b-256 checksum
How to use checksums
dc470f964c2cc5e7497d0070b2bac6e65e324276260ddb06642978ca6e72c0a7
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 22, 2026.

Transparency log

Release files / python_substack-0.8.0-py3-none-any.whl

Download URL python_substack-0.8.0-py3-none-any.whl
Size 35.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
46836b8192282bd7acded4a2e82cf8e922c3d81e46e517721eab633c72f1b68b
BLAKE2b-256 checksum
How to use checksums
d1e864d66eaf22ef73313421d56e59c3d8f43d1d33a803347de54037bd6fca82
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 22, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

2 release files

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.27

2 release files

0.1.26

2 release files

0.1.23

2 release files

0.1.21

2 release files

0.1.20

2 release files

0.1.19

2 release files

0.1.17

2 release files

0.1.16

2 release files

0.1.15

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page