Skip to main content

md-to-medium-deltas

Convert standard Markdown into Medium's undocumented, internal JSON "Deltas" protocol for programmatic publishing.

The Problem

Before 2025, developers could programmatically publish to Medium using their official REST API by sending standard Markdown or HTML.

Medium has since deprecated its public API and stopped issuing integration tokens. The only way to programmatically post rich content to Medium now is to reverse-engineer their internal, React-based web editor protocol, which uses a proprietary JSON "Delta" structure (POST /p/{id}/deltas).

Existing libraries only convert Medium articles to Markdown. This library does the opposite: it parses Markdown and generates exact Delta operations (with correct inline markup text offsets) to reconstruct your article in Medium's editor.

Features

  • Accurate Text Offsets: Automatically calculates character-exact boundaries for inline markup (bold, italic, code).
  • Rich Elements Supported:
    • Headings (H1, H2, H3)
    • Inline formatting (Bold, Italic, Strikethrough, Code)
    • Auto-linked Hyperlinks and Markdown Links
    • Blockquotes
    • Code blocks
    • Ordered and Unordered Lists
  • Intelligent Pre-processing: Fixes edge cases with list elements and correctly drops Markdown dividers that Medium handles natively.

Installation

pip install md-to-medium-deltas

(Note: Requires Python 3.12+)

Usage

from md_to_medium_deltas import markdown_to_deltas

markdown_text = """
# My Awesome Post

This is a paragraph with **bold** and *italic* text, plus a [link](https://github.com).

- Bullet point one
- Bullet point two

```python
print("Hello World")

"""

The start_index indicates the starting delta sequence position.

Pass 1 if your request already created a title delta at index 0.

By default, strip_h1=True drops the leading # Title from the body

so it doesn't duplicate your separate Title field.

deltas = markdown_to_deltas(markdown_text, start_index=1, strip_h1=True)

import json print(json.dumps(deltas, indent=2))


This output can then be directly sent as the payload to Medium's `POST /p/{id}/deltas` internal endpoint.

## How it works

This package uses a robust two-step pipeline:
1. `python-markdown` parses the raw Markdown into compliant HTML.
2. `selectolax` traverses the HTML AST and translates DOM nodes into Medium's Delta paradigm, tracking text accumulation to emit exact inline-markup offsets.

## License
MIT

Metadata

Release files for md-to-medium-deltas 0.1.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 md-to-medium-deltas 0.1.0
File Size Uploaded Provenance
md_to_medium_deltas-0.1.0.tar.gz 6.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for md-to-medium-deltas 0.1.0
File Interpreter ABI Platform
md_to_medium_deltas-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 12.9 kB

Release files / md_to_medium_deltas-0.1.0.tar.gz

Download URL md_to_medium_deltas-0.1.0.tar.gz
Size 6.1 kB
Tags Source
SHA-256 checksum
How to use checksums
4841e334630e8496678eb68d3f73512ebde5e24c0b8bb8c229c1ab469fe7bc61
BLAKE2b-256 checksum
How to use checksums
ab150fd83f15c56a64a087adc541bc2041a4859a6d3a448de20a504c64750687
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / md_to_medium_deltas-0.1.0-py3-none-any.whl

Download URL md_to_medium_deltas-0.1.0-py3-none-any.whl
Size 6.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f014d8c3c4c7e8fbb25eaf0359bd84ca8ce707cb3255bd04adfb2f37b6353209
BLAKE2b-256 checksum
How to use checksums
46a5480502961e332797c7ce1579d4f44b210bf6671cc55b228a9ee5e355d0d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Security for md-to-medium-deltas 0.1.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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