Updated

How to export Notion to Markdown, and what you lose

Export Notion to Markdown step by step: the settings that matter, what databases and links lose, stripping IDs from filenames, and checking nothing was lost.

To export Notion to Markdown, open a page, click the ••• menu at the top right, choose Export, set the format to Markdown & CSV, and switch on Include subpages. For the whole workspace, go to Settings, then General under Workspace, and pick Export all workspace content. You get a zip: ordinary pages become .md files, each database becomes CSV files plus one .md file per row, and uploaded images sit in folders beside their pages.

That zip becomes a folder of plain Markdown files you own after some cleanup. Notion adds a 32-character ID to every filename, databases need a new home, and links need checking. This guide covers each step with free tools and scripts that need no other notes app. For a workspace built on databases, a later section covers the one free tool that converts them through the Notion API.

Run the export

Notion’s help center documents the steps under Export your content. Your settings decide how much cleanup follows.

One page and everything under it

Open the top page of the section you want, click ••• at the upper right, and choose Export. The dialog asks for these:

Setting Choose Why
Export format Markdown & CSV HTML keeps comments and feeds the zip route under databases below. PDF is for printing
Include databases Default view or Current view Picks which view writes the main CSV for each database
Include content Everything Puts uploaded files and images in the zip
Include subpages On Leaving it off exports one page, with links to pages outside the zip
Create folders for subpages On, except on Windows with very deep pages Mirrors your page tree as folders

Include subpages appears on every plan for Markdown and HTML. Notion limits only PDF exports with subpages to Business and Enterprise plans. Small exports download straight away, and large ones arrive by email.

The whole workspace

Go to Settings in the sidebar, select General under Workspace, and choose Export all workspace content. Obsidian’s Notion import guide says this needs workspace admin access, and it works on desktop or web only. Processing can take up to 30 hours, and the emailed link expires after 7 days. With email notifications turned off, the link goes to your Notion inbox.

The export contains only pages the person exporting can open, so other members’ private pages are left out. Notion adds that teamspace settings can hold back more content.

Before you click Export

A few problems fail quietly:

  • Form views do not export. Switch a form to a table view, which exports its questions and responses.
  • The main CSV follows the view’s filter. Rows the view hides are missing from it. Clear the filter first. Most exports also carry an unfiltered _all.csv, described below.
  • Exporting can be switched off. An Enterprise workspace owner can disable it under Settings, then Security, and a guest needs Full access to a page to see Export.
  • Windows Explorer fails on long paths. It cannot extract paths over 260 characters. Turn off Create folders for subpages, or extract with 7-Zip.
  • Huge exports split. Obsidian’s documentation says a multi-gigabyte workspace can arrive as a zip holding Export-<id>-Part-1.zip and further parts, each of which you unzip separately.

Export one small section first and read it before you queue the whole workspace.

What the zip contains

Every file and folder name ends in a space and a 32-character hexadecimal ID:

Projects 1a2b3c4d5e6f78901a2b3c4d5e6f7890.md
Projects 1a2b3c4d5e6f78901a2b3c4d5e6f7890/
    Website redesign 3c4d5e6f7a8b90123c4d5e6f7a8b9012.md
    Website redesign 3c4d5e6f7a8b90123c4d5e6f7a8b9012/
        hero.png
Tasks 5e6f7a8b9c0d12345e6f7a8b9c0d1234.csv
Tasks 5e6f7a8b9c0d12345e6f7a8b9c0d1234_all.csv
Tasks 5e6f7a8b9c0d12345e6f7a8b9c0d1234/
    Fix login 7a8b9c0d1e2f34567a8b9c0d1e2f3456.md

A page with subpages becomes a .md file plus a folder of the same name for its children and attachments. Links between pages are relative paths with spaces written as %20, such as [Website redesign](Projects%201a2b...7890/Website%20redesign%203c4d...9012.md). They resolve as exported because they match the filenames exactly, which is why a hand rename breaks them.

Each database gives you the view’s CSV, usually an _all.csv beside it, and a folder with one page per row. Notion’s help never mentions _all.csv. The ncli converter’s source describes it as “the full view of the database (without filter and sort)”. Row pages carry their properties as plain Property: value lines under the title, which converters such as notion2obsidian parse.

Headings, lists, to-dos, code blocks, quotes, simple tables and uploaded images land as standard Markdown.

What survives and what breaks

Most losses are structure that Markdown and CSV have no place for, and no converter can recover it from the zip. Check this table against your workspace before you cancel anything.

Notion feature In the Markdown & CSV export What to do
Databases CSV files plus a .md file per row Keep the CSV, or move properties into frontmatter (below)
Board, calendar, timeline and gallery views Gone. Only rows remain Rebuild the ones you need in an app with database views, or keep them in Notion
Relations The related page’s title followed by a relative path in parentheses Convert to titles before stripping IDs (below)
Rollups and formulas The value at export time, as text Write down any formula you will need again
Synced blocks Every copy written out in full Keep one copy and link to it from the others
Toggles Markdown has no folding block, so the fold is lost Open a page with toggles in your test export and check it
Callouts HTML, since Markdown has no callout Convert to > [!note] callout syntax
Mentions Page mentions become links, people and dates plain text Reminders set on dates stop firing
Embeds (Figma, YouTube, Google Docs) A link to the source URL Keep the link
Comments Left out Run an HTML export too, which includes page and block comments, resolved and unresolved
Page history Current version only Keep Notion until you no longer need old versions

Notion’s help confirms that callouts export as HTML. The element is an <aside>, which notion2obsidian’s callout converter targets.

Relations between databases have no home in Markdown. The Notion API route below keeps more of each database than the zip does. Stay with Notion when you work through linked databases every day.

Strip the IDs from filenames

The Markdown export leaves you names like Fix login 7a8b9c0d1e2f34567a8b9c0d1e2f3456.md. Links work as they are. Stripping IDs safely needs a tool that renames files and rewrites links in one pass, since a bulk rename in a file manager leaves dead links behind. Work on a copy and keep the original zip untouched.

notion2obsidian runs with no notes app installed, and the Jotura CLI comes with the app you open the folder in.

Tool State in October 2026 Links afterwards Watch for
Jotura CLI rename loop Ships with the free Jotura desktop app Standard Markdown links, still relative Rewrites links in notes only, so convert relations first
notion2obsidian Version 2.6.0 from October 2025, MIT license Wikilinks Needs the Bun runtime. Also converts callouts and database CSVs
Notion-to-Obsidian-Converter Last commit May 30, 2022 Wikilinks Its README says it “is not made to be robust”, and it documents images rewritten as ![Page Title/Image Name.png], which is not valid image syntax

The Jotura CLI’s rename command moves a file or folder and rewrites every link to it in other notes, keeping relative paths relative and %20 intact. It ships inside the free Jotura desktop app: Windows and the Linux .deb put it on your PATH, and on macOS you install it from Settings, Advanced, Command-line tool, as Install and setup describes. The loops below run in any POSIX shell, including Git Bash or WSL on Windows.

Relation paths live in CSV cells and in plain-text property lines, which rename does not touch. Turn them into bare titles first, while every path still matches:

cd ~/notion-export
find . \( -name '*.md' -o -name '*.csv' \) -not -path './.jotura/*' \
  -exec perl -pi -e 's/ \([^()]*%20[0-9a-f]{32}\.md\)//g' {} +

That turns Website redesign (../Projects%201a2b.../Website%20redesign%203c4d....md) into Website redesign. Then strip the IDs, deepest paths first:

find . -depth -mindepth 1 -not -path './.jotura*' > ../notion-paths.txt
while IFS= read -r path; do
  path="${path#./}"
  name="$(basename "$path")"
  clean="$(printf '%s' "$name" | sed -E 's/ [0-9a-f]{32}(_all)?(\.[^.]+)?$/\1\2/')"
  [ "$clean" = "$name" ] && continue
  dir="$(dirname "$path")"
  [ "$dir" = "." ] && dest="$clean" || dest="$dir/$clean"
  jotura --vault . rename "$path" "$dest"
done < ../notion-paths.txt

Tasks <id>.csv becomes Tasks.csv and Tasks <id>_all.csv becomes Tasks_all.csv. Two pages with the same title collide: the second rename is refused with already exists, and that file keeps its ID until you rename it. Add --dry-run after rename to preview, and expect a small hidden .jotura/ folder for the CLI’s lock file.

notion2obsidian is a standalone command-line tool, and the folder it writes is ordinary Markdown. It strips IDs, converts links to wikilinks, adds frontmatter and converts callouts and database CSVs. It runs on Bun, a JavaScript runtime, and will not run under Node.js. Preview with --dry-run first:

bunx notion2obsidian ./Export-abc123.zip ~/Notes --dry-run
bunx notion2obsidian ./Export-*.zip ~/Notes --dataview

A glob such as Export-*.zip processes the parts of a split export together. --dataview writes a note per CSV row, and --no-csv skips database processing entirely. --no-callouts leaves Notion’s HTML callouts as they are.

Turn databases into frontmatter or keep the CSV

Work from each database’s _all.csv where one exists, since it skips the view’s filter. Pick one of three options per database.

Keep the CSV. It holds every value and opens in any spreadsheet, which is enough for an archive.

Convert it to a Markdown table. This suits small reference lists you read more than edit. notion2obsidian writes one for you, and Markdown tables covers editing them by hand.

Move properties into frontmatter. Frontmatter is the YAML block between --- lines at the top of a note, where Markdown editors, static site generators and scripts read properties. The script below writes each CSV row into the frontmatter of the matching row page. Run it after the steps above, and name multi-select columns after the CSV path so they become YAML lists:

# csv_to_frontmatter.py
import csv, json, sys
from collections import Counter
from pathlib import Path

csv_path = Path(sys.argv[1])
rows_dir = csv_path.with_name(csv_path.stem.removesuffix("_all"))
list_columns = set(sys.argv[2:])

with csv_path.open(encoding="utf-8-sig", newline="") as f:
    rows = list(csv.DictReader(f))
title_col = next(iter(rows[0])) if rows else None
counts = Counter(row[title_col] for row in rows)

for row in rows:
    title = row[title_col]
    props = {k: v for k, v in row.items() if k != title_col and v}
    note = rows_dir / f"{title}.md"
    if counts[title] > 1:
        print(f"skipped, {counts[title]} rows share this title: {title}")
    elif not props:
        print(f"skipped, no values: {title}")
    elif not note.exists():
        print(f"no file for row: {title}")
    elif note.read_bytes().startswith(b"---"):
        print(f"skipped, already has frontmatter: {note}")
    else:
        lines = ["---"]
        for key, value in props.items():
            if key in list_columns:
                value = [v.strip() for v in value.split(",") if v.strip()]
            lines.append(f"{json.dumps(key, ensure_ascii=False)}: {json.dumps(value, ensure_ascii=False)}")
        lines.append("---\n")
        note.write_bytes("\n".join(lines).encode("utf-8") + note.read_bytes())
        print(f"updated: {note}")
python3 csv_to_frontmatter.py Tasks_all.csv Tags

The script skips rows with no values and rows that share a title, since it cannot tell their pages apart. It reports rows with no matching file: Notion-to-Obsidian-Converter’s README notes that Notion drops parentheses and dashes from titles when it names files, so compare those names by hand. Dates arrive as the CSV’s text, such as October 8, 2026. Once the frontmatter is right, delete the duplicate Property: value lines from each body.

Databases through the Notion API

The Markdown export cannot recover formulas or views. One free tool reads them from the Notion API instead: Obsidian’s official Importer plugin, version 3.1.14 on October 7, 2026. It runs inside the free Obsidian app, version 1.13 or later, where you enable it under Settings, then Community plugins. The folder it writes is plain Markdown and opens in Jotura unchanged. Obsidian’s Notion import guide recommends this route over Notion’s Markdown export, which it says “omits important data.”

API route. In your Notion Connections dashboard, create a connection with Access token as the authentication method and copy the token, which starts with ntn_. Under the connection’s Content access tab, add every page and database you want, since the connection sees nothing else. In Importer, choose Notion (API), paste the token, click Load, pick what to import and run it.

Each database arrives as a folder named after it, holding a .base file for the view and its formulas, per Obsidian’s import guide. An Update mode, added in version 2.3.0, re-runs the import later. Obsidian lists the limits: only each database’s primary view imports, linked data sources are skipped, a few formula functions do not convert, and rate limits slow large workspaces.

Zip route. Export the whole workspace as HTML with Include everything and Create folders for subpages. In Importer, choose Notion (.zip) and import everything in one pass so links between pages resolve. This route works offline with no token, and it does not keep databases.

Notion writes links as [Title](Folder/Page%20name.md). Jotura and most other Markdown editors decode %20 and follow them as they are. notion2obsidian converts them to [[Page name]] wikilinks instead, and wikilinks and backlinks in plain Markdown covers the tradeoff between the two styles.

Links you pasted as full Notion URLs, and some relation values, point at notion.so and stop working once you leave. This grep finds them, along with any encoded ID the cleanup missed:

grep -rn --include='*.md' --include='*.csv' -E 'notion\.(so|site)|%20[0-9a-f]{32}' .

Checklist: confirm nothing was lost

Run these before you cancel your Notion plan or delete anything.

  1. Count database rows. Compare each _all.csv row count with the files in its folder and with the count Notion shows under the table:

    python3 -c "import csv,sys; print(sum(1 for _ in csv.DictReader(open(sys.argv[1], encoding='utf-8-sig'))))" Tasks_all.csv
    ls Tasks/*.md | wc -l
    
  2. Find leftover IDs. This lists every name that still carries one:

    find . | grep -E ' [0-9a-f]{32}'
    
  3. Find dead links. With the Jotura CLI, this prints every link and image embed that resolves to nothing:

    find . -name '*.md' -not -path './.jotura/*' | while IFS= read -r f; do
      jotura --vault . links "${f#./}" --json \
        | grep -A2 '"resolved": \[\]' | grep '"target"' | sed "s|^ *|${f#./}: |"
    done
    
  4. Find unconverted callouts. grep -rln --include='*.md' '<aside' . lists notes still holding Notion’s HTML callouts.

  5. Open your five longest pages. Check toggles, and synced blocks that now appear in several places.

  6. Keep comments. Store an HTML export beside the Markdown.

  7. Keep the original zip. Put it on a drive and in one backup. Notion says re-uploading an export will not instantly recreate a workspace.

Opening the folder in Jotura

Jotura opens the cleaned folder as it stands, with no import step, and leaves the files where they are. It follows Notion’s percent-encoded links as exported, and the wikilinks notion2obsidian writes. Notion’s to-dos arrive as - [ ] checkboxes, which Jotura’s Tasks pane collects from every note. Add @due(2026-11-01) to a task line to give it a due date.

Frontmatter written by the script above stays byte for byte, and Jotura reads tags and aliases from it. The Tags pane counts those tags together with inline #tags. CSV files open as searchable text, and renaming a note in the file tree rewrites the links to it. Raw HTML shows as plain text, so convert Notion’s <aside> callouts to > [!note] callout syntax first.

A folder written by Obsidian’s Importer opens the same way. Jotura shows its .base files as plain text, and Coming from Obsidian lists the rest of what carries over.

Jotura has no databases or database views, and no Notion importer. It has no iOS app, and the Android app reaches your desktop notes only through paid Jotura Sync. Stay with Notion when your work lives in database views. How Jotura and Notion compare covers the rest, and Notion alternatives covers AppFlowy and Anytype, which have databases.

Notion’s Markdown API, for scripts

Notion’s API returns any page as Markdown through GET /v1/pages/{page_id}/markdown, with the Notion-Version: 2026-03-11 header. It suits scripts that pull a few pages on a schedule:

curl "https://api.notion.com/v1/pages/$PAGE_ID/markdown" \
  -H "Authorization: Bearer $NOTION_TOKEN" \
  -H "Notion-Version: 2026-03-11"

The response’s markdown field uses Notion’s enhanced Markdown, where callouts come back as <callout> tags and child pages as <page> tags. Plain Markdown tools show those as text. Notion’s Markdown guide lists every tag and the truncation limit of roughly 20,000 blocks.

Frequently asked questions

Can I export Notion to Markdown on the free plan?

Yes. Any page exports as Markdown & CSV with its subpages on every plan, and a workspace admin on the free plan can export everything from Settings, then General. Only PDF exports with subpages need a Business or Enterprise plan.

Does the Notion Markdown export keep databases?

The values come through. Each database becomes CSV files plus a Markdown file per row, and views, relations, rollups and formulas stay behind in Notion. Obsidian’s Importer plugin reads databases through the Notion API instead, and writes each one as a folder with a .base view file.

Should I use the Markdown or the HTML export?

Markdown & CSV gives you plain Markdown files that any app opens, and every cleanup step in this guide starts from it. HTML is the only export that includes comments, and it is the format Obsidian’s Importer reads on its zip route.

Can Jotura import a Notion export?

Jotura has no Notion importer. It opens the folder of Markdown you get after the cleanup in this guide, with no import step, and follows Notion’s links as exported.

Why do my exported files have long strings of letters and numbers in their names?

Notion appends each page’s 32-character ID to its filename, which keeps pages with the same title apart. Links point at those exact names, so strip IDs only with a tool that rewrites links too.

How long does a Notion workspace export take?

A full workspace export can take up to 30 hours to process, according to Notion, and the emailed download link expires after 7 days.

Evernote to Markdown: export ENEX and convert your notes2026-10-10
Evernote to Markdown, step by step: export ENEX from the desktop app, convert it with Yarle, evernote2md or Obsidian Importer, then check links and files.

More in Migrating.

Download free

Jotura is free, and your notes stay plain markdown files you keep forever.