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.
- 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
- 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
pip install md2notionpageFor development:
git clone https://github.com/markomanninen/md2notion.git
cd md2notion
pip install -e .- Go to https://www.notion.so/my-integrations
- Click "+ New integration"
- Give it a name and select the workspace
- Copy the "Internal Integration Token"
- 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:
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!
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# 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-herefrom 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..."
)# Heading Level 1
## Heading Level 2
### Heading Level 3- 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$
$$
x = \sqrt{y^2 + z^2}
$$Unordered:
- Item 1
- Item 2
- Nested itemOrdered:
1. First item
2. Second item
1. Nested item[Link text](https://example.com)```python
def hello_world():
print("Hello, world!")
```> This is a quoteWith 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.
---With caption:
Without caption:
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
# 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 -vTest the splitting and batching logic with large documents:
python scripts/stress_test.pyThis creates a page with:
- 3000+ character paragraph (tests text splitting)
- 150 list items (tests batch processing)
- Update version in
pyproject.toml - Build the package:
python -m build
- Upload to PyPI:
python -m twine upload dist/*
notion-client- Official Notion API clientpython-dotenv- Environment variable management
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Built with the Notion API
- Inspired by the need for easy Markdown-to-Notion conversion