将 Notion 页面和数据库导出为本地 Markdown 文件,支持增量更新和附件下载。
- 增量同步 — 仅导出上次同步后有变更的页面,无需每次全量重新开始
- 流式写入 —
--all模式下边获取边写入,无需等待全部完成 - 附件下载 — 自动下载图片、PDF、文件等附件到本地,Markdown 中使用相对路径引用
- 数据库按目录分组 — 数据库的每条记录生成独立
.md文件,统一放在数据库名称的子目录下 - data_source API — 支持 Notion 2025-09-03+ 新 API
- 速率限制 — 自动遵守 Notion 3 req/s 限制,429 响应自动重试
- file_upload 解析 — 自动解析 Notion 新版文件上传类型,获取临时下载链接
- 20+ Block 类型 — 支持段落、标题、列表、代码、引用、表格、数学公式、Callout、Toggle 等
go install github.com/luoshuhui/notion2md@latest或从源码构建:
git clone https://github.com/luoshuhui/notion2md.git
cd notion2md
go build -o notion2md .- 创建 Notion Integration:https://www.notion.so/my-integrations
- 获取 Integration Token(以
ntn_或secret_开头) - 在 Notion 中将 Integration 添加到要导出的页面/数据库(页面右上角 ··· → Connections → 添加你的 Integration)
# 方式一:通过 .env 文件配置(推荐)
echo 'NOTION_TOKEN=ntn_your_token_here' > .env
# 方式二:通过环境变量配置
export NOTION_TOKEN="ntn_your_token_here"
# 列出可访问的页面和数据库
notion2md list
# 导出指定页面
notion2md sync -p <PAGE_ID>
# 导出指定数据库
notion2md sync -d <DATABASE_ID>
# 导出所有可访问内容
notion2md sync --all
# 增量导出(默认模式,仅导出变更部分)
notion2md sync -p <PAGE_ID>列出 Integration 可访问的所有页面和数据库。
notion2md list
notion2md list --ids-only # 仅输出 ID,便于脚本处理输出示例:
Found 5 accessible resources:
1. 📄 项目文档
ID: abc123def456-...
Type: page
URL: https://notion.so/...
2. 📊 任务跟踪
ID: 789ghi012-...
Type: database
URL: https://notion.so/...
将 Notion 内容同步导出为本地 Markdown 文件。
notion2md sync [flags]| Flag | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
--token |
NOTION_TOKEN |
(必填) | Notion Integration Token |
--base-url |
NOTION_BASE_URL |
https://api.notion.com |
API 基地址(用于代理) |
配置优先级:命令行 flag > 环境变量 >
.env文件在当前目录创建
.env文件即可自动加载:NOTION_TOKEN=ntn_your_token_here NOTION_BASE_URL=https://api.notion.com # 可选
| Flag | 默认值 | 说明 |
|---|---|---|
-o, --output |
./notion-export |
输出目录 |
--mode |
incremental |
同步模式:full 或 incremental |
-p, --page |
页面 ID(可重复指定多个) | |
-d, --database |
数据库 ID(可重复指定多个) | |
--all |
false |
导出所有可访问内容 |
--download-images |
true |
下载图片到本地 |
--download-files |
true |
下载 PDF/文件到本地 |
-v, --verbose |
false |
启用调试日志 |
至少需要指定
--page、--database或--all之一。
示例:
# 全量导出指定页面
notion2md sync -p abc123def456 --mode full
# 增量导出多个页面
notion2md sync -p page1 -p page2 -p page3
# 导出所有内容到指定目录
notion2md sync --all -o ~/notion-backup
# 仅导出 Markdown,不下载附件
notion2md sync -p abc123 --download-images=false --download-files=false
# 启用调试日志
notion2md sync --all -v查看同步状态信息。
notion2md status
notion2md status -o /path/to/output输出示例:
=== Notion2md Sync State ===
Output directory: ./notion-export
State file: ./notion-export/.notion2md/sync-state.json
Total pages tracked: 23
Total syncs: 5
Last sync: 2026-05-26 14:30:00
Last full sync: 2026-05-25 09:00:00
重置同步状态,下次运行将执行全量同步。
notion2md reset-state --forcenotion-export/ # 输出目录
.notion2md/
sync-state.json # 增量同步状态(自动管理)
项目文档.md # 页面 → Markdown 文件
项目文档/
screenshot.png # 该页面的图片附件
design-spec.pdf # 该页面的文件附件
ReadItLater/ # 数据库 → 以数据库名命名的子目录
某篇文章标题.md # 每条记录独立 Markdown 文件
另一篇文章标题.md
...
另一个数据库/
记录1.md
记录2.md
独立页面.md
独立页面/
photo.jpg
- 普通页面生成一个
.md文件,附件存放在同名子目录中 - 数据库的每条记录生成独立
.md文件,统一放在数据库名称的子目录下 - Markdown 中使用相对路径引用附件(如
./项目文档/screenshot.png),离线可用 - 同步状态保存在
.notion2md/sync-state.json中,删除输出目录即重新开始
- 首次运行执行全量同步,记录每个页面的
last_edited_time - 后续运行调用 Notion Search API 获取所有页面的最新
last_edited_time - 逐页对比时间戳,仅对变更的页面重新获取内容
- 数据库级别的增量:检测到数据库变更时,逐记录对比时间,仅重新获取变更的记录
- 自动检测删除:上轮存在但本轮消失的页面标记为已删除,本地文件同步移除
首次同步: 全量导出 100 页 → 100 个 Markdown 文件
增量同步: 仅 3 页有变更 → 只重写 3 个文件,97 个跳过
如需通过代理访问 Notion API:
export NOTION_BASE_URL="https://your-proxy.example.com"
notion2md sync --all本项目从 WeKnora 的 Notion Connector 提取而来,主要变更:
| 变更 | 说明 |
|---|---|
| 移除框架依赖 | 替换 types.FetchedItem、types.SyncCursor、logger 等为独立实现 |
| 添加 CLI 层 | 基于 cobra + viper 的命令行界面 |
| 添加文件输出 | Markdown 写入本地文件 + 附件下载 + URL 重写为相对路径 |
| 添加状态持久化 | 同步状态保存为 JSON 文件,重启后可恢复增量同步 |
| 流式写入 | --all 模式下边获取边写入,不累积内存 |
| 数据库按目录分组 | 每条记录独立 .md 文件,放在数据库同名的子目录下 |
| 日志替换 | logger.Infof → log/slog,零外部日志依赖 |
MIT