Skip to main content

md2notionpage

A Python package to convert Markdown text into Notion pages. This module provides functionality to create Notion pages from Markdown text, parse Markdown into Notion blocks, and process inline formatting.

Features

  • Rich Markdown support - Headers, lists, code blocks, tables, images, and more
  • Smart text splitting - Automatically handles Notion's 2000-character limit
  • Batch processing - Efficiently handles large documents with 100+ blocks
  • Database entries - Create entries in Notion databases with configurable title property
  • Cover images - Optional cover image support
  • CLI & Python API - Use as a command-line tool or import as a module
  • Helpful error messages - Clear guidance for common issues

Installation

pip install md2notionpage

For development:

git clone https://github.com/markomanninen/md2notion.git
cd md2notion
pip install -e .

Setup

1. Create a Notion Integration

  1. Go to https://www.notion.so/my-integrations
  2. Click "+ New integration"
  3. Give it a name and select the workspace
  4. Copy the "Internal Integration Token"

2. Get Your Parent Page ID

  1. Open the page in Notion where you want to create sub-pages
  2. Click "Share" → "Copy link"
  3. Extract the 32-character ID from the URL
    • Example: https://notion.so/My-Page-abc123def456...
    • Page ID: abc123def456...

3. Grant Integration Access

Important: You must grant your integration access to the parent page:

  1. Open the parent page in Notion
  2. Click "..." (more options) → "Add connections"
  3. Select your integration from the list

Without this step, you'll get "restricted_resource" errors!

4. Configure Environment Variables

Create a .env file in your project directory:

NOTION_SECRET=your_notion_integration_token_here
NOTION_PARENT_PAGE_ID=your_target_parent_page_id_here

Usage

Command Line Interface

# Basic usage
md2notionpage example.md

# With custom title
md2notionpage example.md --title "My Custom Title"

# With cover image
md2notionpage example.md --cover_url "https://images.unsplash.com/photo-123..."

# Specify parent page ID directly
md2notionpage example.md parent-page-id-here

Python Module

from md2notionpage import md2notionpage

markdown_text = """
# My Page
This is a Notion page created from Markdown content.

## Features
- **Bold text**
- *Italic text*
- `Code inline`
"""

title = 'My Notion Page'
parent_page_id = 'YOUR_PARENT_PAGE_ID'

# Create page
notion_page_url = md2notionpage(markdown_text, title, parent_page_id)
print(f"Page created: {notion_page_url}")

# With cover image
notion_page_url = md2notionpage(
    markdown_text, 
    title, 
    parent_page_id,
    cover_url="https://images.unsplash.com/photo-123..."
)

Creating Database Entries

You can also create entries in a Notion database instead of sub-pages:

from md2notionpage import md2notionpage

markdown_text = "Task description with **rich** formatting..."
title = "My Task"
database_id = "YOUR_DATABASE_ID"

# Basic usage - uses the default title property "Name"
url = md2notionpage(
    markdown_text,
    title,
    database_id,
    parent_type='database'
)

# If your database title property has a different name (e.g., "Task")
url = md2notionpage(
    markdown_text,
    title,
    database_id,
    parent_type='database',
    title_property_name='Task'
)

# With custom properties (for databases with additional fields)
url = md2notionpage(
    markdown_text,
    title,
    database_id,
    parent_type='database',
    properties={
        "Name": {"title": [{"text": {"content": "My Task"}}]},
        "Status": {"select": {"name": "In Progress"}},
        "Priority": {"number": 1}
    }
)

Note: The title_property_name parameter defaults to 'Name' which matches Notion's default. If your database uses a custom name for the title property (e.g., "Task", "Item", "Title"), specify it with title_property_name.

Supported Markdown Features

Headings

# Heading Level 1
## Heading Level 2
### Heading Level 3

Text Formatting

  • Bold Text: **bold** or __bold__
  • Italic Text: *italic* or _italic_
  • Bold and Italic: __*text*__ or **_text_**
  • Strikethrough: ~text~
  • Inline Code: `code`
  • Inline LaTeX: $x = y^2$

LaTeX Blocks

$$
x = \sqrt{y^2 + z^2}
$$

Lists

Unordered:

- Item 1
- Item 2
  - Nested item

Ordered:

1. First item
2. Second item
   1. Nested item
[Link text](https://example.com)

Code Blocks

```python
def hello_world():
    print("Hello, world!")
```

Blockquotes

> This is a quote

Tables

With headers:

| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Content  | Content  | Content  |

Without headers:

| Content 1.1 | Content 2.1 | Content 3.1 |
| Content 1.2 | Content 2.2 | Content 3.2 |

Tables are rendered as LaTeX/KaTeX in Notion.

Horizontal Lines

---

Images

With caption:

![Alt Text](https://example.com/image.jpg)

Without caption:

![](https://example.com/image.jpg)

Error Handling

The tool provides helpful error messages for common issues:

  • Invalid API token - Instructions for creating an integration
  • Invalid parent page ID - How to find the correct page ID
  • Page not found - Verification steps
  • Access denied - How to grant integration access
  • Invalid cover URL - Cover image requirements

Development

Running Tests

# Install dev dependencies
pip install -e .[dev]

# Run all tests
python -m pytest -v

# Run specific test file
python -m pytest tests/test_md2notionpage.py -v

Stress Testing

Test the splitting and batching logic with large documents:

python scripts/stress_test.py

This creates a page with:

  • 3000+ character paragraph (tests text splitting)
  • 150 list items (tests batch processing)

Publishing

  1. Update version in pyproject.toml
  2. Build the package:
    python -m build
    
  3. Upload to PyPI:
    python -m twine upload dist/*
    

Dependencies

  • notion-client - Official Notion API client
  • python-dotenv - Environment variable management

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Acknowledgments

  • Built with the Notion API
  • Inspired by the need for easy Markdown-to-Notion conversion

Metadata

Release files for md2notionpage 0.1.6

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

Source distribution (sdist)

Source distribution for md2notionpage 0.1.6
File Size Uploaded Provenance
md2notionpage-0.1.6.tar.gz 20.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for md2notionpage 0.1.6
File Interpreter ABI Platform
md2notionpage-0.1.6-py3-none-any.whl Python 3 none any Details

Total release size: 33.9 kB

Release files / md2notionpage-0.1.6.tar.gz

Download URL md2notionpage-0.1.6.tar.gz
Size 20.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b6419b4141a4e62fdc89b6dbd6b7239aea9a10dc01066d913617d42f49f27bb4
BLAKE2b-256 checksum
How to use checksums
df7c2c598b40ebfb5b77f034393418e38238654dc607e0dbedf753c947c64938
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 Oct 12, 2026.

Transparency log

Release files / md2notionpage-0.1.6-py3-none-any.whl

Download URL md2notionpage-0.1.6-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
24459e1cd3faa02270f97b9bc4f4d03368f23d75bb755ef3d8ba42c6f9a83fe4
BLAKE2b-256 checksum
How to use checksums
63181045006d5ee0b34ac46fe4adeb4af61b90356db562aa2bb5b12acc598210
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 Oct 12, 2026.

Transparency log

Security for md2notionpage 0.1.6

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for md2notionpage-0.1.6.tar.gz

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 Oct 12, 2026.

Transparency log

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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