Fetch any public Notion page and print it as Markdown — no token, no headless browser.
Project description
notion-site-fetch
Fetch any public Notion page and print it as Markdown to stdout. No API token. No login. No headless browser. Just plain HTTPS calls to the endpoints Notion's own web client uses.
If the page opens for anyone in an anonymous browser tab, this tool can read it.
Install / run
The package is published on PyPI. The fastest way to run it is with
uvx, which fetches and
executes the tool on demand:
uvx notion-site-fetch https://example.notion.site/ > page.md
You can also install it permanently:
uv tool install notion-site-fetch
notion-site-fetch https://example.notion.site/ > page.md
# or with pipx:
pipx install notion-site-fetch
Requires Python 3.13+.
Usage
notion-site-fetch <url>
Markdown is written to stdout. Use shell redirection to save it:
notion-site-fetch https://example.notion.site/ > page.md
notion-site-fetch https://example.notion.site/Some-Subpage >> notes.md
Errors go to stderr; the exit code is non-zero on failure.
Accepted URL forms
| URL | What it fetches |
|---|---|
https://<sub>.notion.site/ |
Site's public home page |
https://<sub>.notion.site/<slug-or-id> |
A specific page on the public site |
https://www.notion.so/<...>-<32-char-page-id> |
A notion.so page URL |
Any URL whose path ends in a 32-character Notion page id is accepted
even without a .notion.site host.
Behavior
- Sub-pages stay as links. Only the page you ask for is fetched. To expand a linked sub-page, run the tool again with its URL.
- Toggles/dropdowns are expanded inline. Nothing is hidden behind a fold; nested toggles are followed recursively.
- Private pages fail clearly. If the page isn't publicly readable, the tool exits with an error rather than silently returning nothing.
- Pagination is handled for long pages.
What gets rendered
Headings (H1–H4), paragraphs, bold/italic/strikethrough/code inline formatting, links, bulleted/numbered/to-do/toggle lists with nesting, quotes, callouts (as blockquotes), dividers, code blocks (with language), images, bookmarks, video/file/PDF/audio embeds (as links), and inline equations.
Things that are deliberately skipped or simplified: table-of-contents and breadcrumb blocks (Markdown renderers generate their own), column-layout wrappers (children are flattened into normal flow), and collection-view databases (only the title is emitted — Notion does not expose row-level data to anonymous viewers).
How it works
Notion's public sites are served as an empty React shell and hydrated by client-side calls to three internal endpoints:
POST /api/v3/getPublicPageDatawith{"spaceDomain": "<sub>"}resolves a*.notion.sitesubdomain to aspaceId.POST /api/v3/getPublicSpaceDatawith thatspaceIdreturns thepublicHomePageblock id — the root page of the site.POST /api/v3/loadCachedPageChunkV2walks the page block by block, paginated with a cursor. Toggle children that the chunk loader skips are pulled in afterwards viasyncRecordValues.
All endpoints are unauthenticated and return JSON. The tool issues
these requests against the site's own subdomain (*.notion.site) where
possible to avoid Notion's cross-cell routing errors on www.notion.so.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notion_site_fetch-0.1.0.tar.gz.
File metadata
- Download URL: notion_site_fetch-0.1.0.tar.gz
- Upload date:
- Size: 7.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4702a4907d096495086cbf86e03c88a7e8c798db657871bf616fe1c51472b0de
|
|
| MD5 |
4870a07141027338ea8f6b1215fb8e41
|
|
| BLAKE2b-256 |
b4d734123a86035e9d27e6fd1847c46404b25b296b318e69dcc1a823e833a756
|
File details
Details for the file notion_site_fetch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: notion_site_fetch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c5c3fefaa600a9cc100ef895b640471652e61029891d24449f137da352ff7d8
|
|
| MD5 |
5160a4ac6dae960804ac2bd33a5cab1f
|
|
| BLAKE2b-256 |
913850974ca6c697530e1f404dcb7dba78bc709058bf4d6866da237fa1ef810c
|