Download any Obsidian Publish site locally, even if it's password-protected.
Needed a way to back up and download entire Obsidian Publish sites. Since there's no official "export" feature for viewers, doing this manually is incredibly tedious.
This script handles the heavy lifting. It authenticates just like the official web app, fetches the site's internal manifest, and downloads everything in parallel. It even handles Windows filename restrictions so your files won't get messed up.
- Bypasses passwords: Fully supports password-protected sites using Obsidian's native authentication handshake.
- Fast & Concurrent: Downloads multiple files at once (10 threads by default).
- Resumable: If your connection drops, it skips files you already have.
- Smart caching: Type your password once; it caches your token for future runs.
- Resilient: Automatically retries failed requests with exponential backoff.
The easiest way to run this is with uv, but standard Python and pip work perfectly fine too.
First, install the dependencies (requests and tqdm):
# With uv (recommended)
uv pip install requests tqdm
# Or standard pip
pip install requests tqdmuv run download.py [options] <URL> <FOLDER>Just point it at the URL and give it a destination folder. It will create the folder if it doesn't exist.
uv run download.py https://help.obsidian.md/ vaultAdd the --password flag to securely enter the site's password.
uv run download.py https://my-private-site.com/ vault --passwordNote: Your token gets saved as .obsidian-publish-token in your destination folder. On future runs, it uses this cached token automatically so you don't have to keep typing your password.
If you have a massive site or your internet cuts out, you can run the same command with --resume to skip files you've already downloaded. Feel free to crank up the --workers if you want it to go faster!
uv run download.py https://example.com/ vault --resume --workers 20Here are the different flags you can pass to the script:
| Flag | Description | Default |
|---|---|---|
-p, --password |
Prompt for the site's password | Off |
-w, --workers |
Number of concurrent downloads | 10 |
-r, --resume |
Skip files that already exist on disk | Off |
--max-retries |
How many times to retry a failed file | 5 |
--retry-delay |
Base seconds to wait before retrying | 3 |
--no-sanitize |
Don't rename invalid Windows characters | Off |