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
- Go to https://www.notion.so/my-integrations
- Click "+ New integration"
- Give it a name and select the workspace
- Copy the "Internal Integration Token"
2. Get Your Parent Page ID
- Open the page in Notion where you want to create sub-pages
- Click "Share" → "Copy link"
- Extract the 32-character ID from the URL
- Example:
https://notion.so/My-Page-abc123def456... - Page ID:
abc123def456...
- Example:
3. Grant Integration Access
Important: You must grant your integration access to the parent page:
- Open the parent page in Notion
- Click "..." (more options) → "Add connections"
- 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
Links
[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:

Without caption:

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
- Update version in
pyproject.toml - Build the package:
python -m build
- Upload to PyPI:
python -m twine upload dist/*
Dependencies
notion-client- Official Notion API clientpython-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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| md2notionpage-0.1.6.tar.gz | 20.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.