Export a Microsoft OneNote notebook to ordinary Markdown files, keeping the structure, the pictures and the original dates — then optionally upload the result to SharePoint with those dates intact.
Every OneNote page becomes a .md file (plain text you can open in Notepad, VS Code,
Obsidian, or import into another system). Pictures and attachments are saved alongside.
Your notebooks are never modified — the tools only read from OneNote.
Built by Sope Web Technologies. MIT licensed, so use it freely.
| Script | What it does | Needs |
|---|---|---|
Export-OneNoteMarkdown.ps1 |
Exports one notebook to Markdown | Windows PowerShell 5.1 |
Check-ImageDownloads.ps1 |
Tells you whether OneNote has actually downloaded all the pictures yet | Windows PowerShell 5.1 |
Upload-ToSharePoint.ps1 |
Uploads the result to SharePoint, preserving file and folder dates | PowerShell 7 |
The PowerShell versions really are different, and neither can compromise. OneNote's automation interface doesn't work in PowerShell 7, and the SharePoint module (PnP.PowerShell) is .NET Core only so it doesn't work in 5.1. Each script checks and tells you if you're in the wrong one.
- Windows, with the OneNote desktop app — the one from Microsoft 365. The retired "OneNote for Windows 10" Store app has no automation interface and will not work.
- The notebook open in OneNote and finished syncing. If you can't see it in OneNote, the tool can't either.
- Don't run as Administrator. OneNote won't talk to an elevated process. No special rights are needed.
-
In File Explorer, right-click
Export-OneNoteMarkdown.ps1and choose "Run with PowerShell" (on Windows 11 you may need "Show more options" first). -
It lists the notebooks you have open:
Which notebook do you want to export? 1. Active Projects 664 pages 2. Marketing Notes 232 pages 3. Sales Notebook 2161 pages Type a number from 1 to 3 and press Enter -
Type the number and press Enter.
-
Leave OneNote alone while it runs. The tool pages through OneNote to collect pictures, so OneNote will look like it's being driven by a ghost. That's normal.
Roughly 1–2 seconds per page. A 200-page notebook takes a few minutes; 2,000 pages closer to half an hour.
In an out folder next to the script, mirroring your OneNote structure:
out\
Sales Notebook\
1. Enquiry-Qualified\ <- a OneNote section
Acme Corp\
First Call.md
media\ <- pictures for these pages
first-call-01.png
Sections become folders. If a page has sub-pages beneath it, that page becomes a
folder holding them — so a page Jane Smith with a Phone Screen sub-page gives you
Jane Smith\Phone Screen.md. This keeps pages apart that happen to share a name.
Each file starts with the page title as a heading, then the content.
OneNote keeps page text on your computer but fetches pictures only when it needs them. Anything it hasn't downloaded can't be exported, and OneNote never tells you when it's finished fetching. This script measures it:
powershell.exe -NoProfile -File .\Check-ImageDownloads.ps1 Pictures found 4,284
Downloaded, ready 1,703
Still missing 2,581
Complete 39.8%
To get the rest: in OneNote, right-click the notebook → Notebook Sync Status → tick Download all files and images. That setting is per notebook, so set it on each one you plan to export. Leave OneNote open and connected, then re-check:
powershell.exe -NoProfile -File .\Check-ImageDownloads.ps1 -Notebook "Sales Notebook" -Recheck-Recheck only re-tests the pages that were short last time, so it takes seconds. When
"Still missing" reaches 0, run the export.
If the number stops falling, make OneNote fetch them directly:
powershell.exe -NoProfile -File .\Check-ImageDownloads.ps1 -Notebook "Sales Notebook" -Recheck -Nudge-Nudge opens each page so OneNote downloads that page's pictures there and then.
It's slower but doesn't rely on the background download. Some stubborn images may still
never arrive — OneNote only fetches what it actually renders. Any that can't be saved are
listed in _export-log.csv, so nothing fails silently.
A normal upload stamps everything with today's date. This uploads over the Graph API and then writes the real Created/Modified dates back onto both files and folders.
pwsh -File .\Upload-ToSharePoint.ps1 `
-SourceFolder .\out `
-SiteUrl https://contoso.sharepoint.com/sites/Marketing `
-LibraryPath "Documents/OneNote Exports"Add -WhatIf first for a dry run. Use -FolderDatesOnly to fix folder dates on a tree
you've already uploaded, and -SkipFolderDates to upload without them.
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module PnP.PowerShell -Scope CurrentUserThe Graph sign-in needs no app registration. Folder dates do, because folder Created/Modified can only be written through the SharePoint API, and app registrations are specific to one tenant — so this tool doesn't ship one. Create yours once:
Register-PnPEntraIDAppForInteractiveLogin `
-ApplicationName 'OneNote Export' `
-Tenant contoso.onmicrosoft.com `
-SharePointDelegatePermissions AllSites.FullControlIt prints a client ID. Save it once and forget it:
setx PNPPOWERSHELL_CLIENTID "<the id it printed>"Creating the app registration and consenting to that permission needs an administrator. Overriding Created/Modified also needs at least Manage Permissions (Full Control) on the target site — the script reads the dates back afterwards and warns you if SharePoint didn't keep them.
Comes across
- Headings, paragraphs, bullet and numbered lists, including nesting
- Bold, italic, underline, strikethrough and highlighting
- Tick boxes (To Do and attendance tags), including whether they're ticked
- Tables, pictures, file attachments
- Links, including links between OneNote pages (rewritten to relative file links)
Doesn't come across
- Handwriting and drawings. These can't become text. Affected pages get a note saying so; export those to PDF from OneNote separately if you need them.
- Password-protected sections. Invisible to the tool. Unlock them in OneNote first.
Any skipped are listed in
_locked-sections.txt. - Page layout, text colours and font sizes. The words are kept; the visual styling is not.
- Embedded audio and video. The page notes that a file was there.
Re-running is safe and quick — it only re-exports pages that changed in OneNote since last time. So you can re-run whenever you want to pick up recent edits.
- Renaming or deleting a page in OneNote leaves the old file behind. These are listed in
_orphaned-files.txt. Nothing is ever deleted for you — review and remove them yourself. - Keep
_export-log.csvwhere it is. That's how the tool knows what it has already done, and it records any problems page by page.
Something about "Administrator" or 0x80080005
You've opened PowerShell as an administrator. Close it and right-click the script normally.
Something about "Windows PowerShell 5.1" Your machine launched PowerShell 7 instead. Right-click the script → "Show more options" → "Run with PowerShell". If it keeps happening the file association needs changing.
"Could not load type ... Microsoft.Identity.Client" during upload The Graph and SharePoint modules ship different versions of the same sign-in library and only one can load per session. Open a fresh PowerShell 7 window and run it again.
"Could not find a notebook called ..." The tool lists what it can see. If yours isn't there, open it in OneNote and let it sync.
It seems stuck Large notebooks genuinely take a long time, and the tool pauses while OneNote fetches pictures. If the page counter is still climbing, it's working.
| Option | Script | What it does |
|---|---|---|
-Notebook "name" |
export, check | Skip the menu |
-OutputRoot "C:\path" |
export | Save somewhere other than out |
-Force |
export, upload | Redo everything, including unchanged items |
-RetryFailed |
export | Redo only pages that had a problem last time |
-IncludeFrontMatter |
export | Add YAML metadata above each page's heading |
-FlattenPageGroups |
export | Don't turn pages with sub-pages into folders |
-UnderlineAs |
export | html (default), plus, bold, italic, none |
-NoHydrateImages |
export | Don't wait for OneNote to fetch pictures (faster, loses more) |
-Recheck / -Nudge |
check | Fast re-test / force download |
-FolderDatesOnly |
upload | Fix folder dates on an already-uploaded tree |
-SkipFolderDates |
upload | Upload without the second sign-in |
-WhatIf |
upload | Dry run |
Run Get-Help .\Export-OneNoteMarkdown.ps1 -Full for the complete set.
MIT — see LICENSE. Provided as-is, with no warranty. Contributions and issue reports are welcome.