Skip to content

The Complete Guide to Exporting Notion Data (HTML, PDF, Markdown & API)

Notion allows exporting workspace data in HTML, Markdown with CSV, and PDF, but HTML is the only format that preserves page hierarchy for migrations to platforms like Confluence. For automation, the Notion API returns JSON block data instead of direct export files, requiring a translation layer and careful handling of rate limits (3 requests per second) when extracting large workspaces.

Raaj Raaj · · 9 min read
The Complete Guide to Exporting Notion Data (HTML, PDF, Markdown & API)
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Executive Summary (TL;DR)

Notion supports manual data exports in PDF, HTML, and Markdown/CSV formats — both at the individual page level and as a full workspace export (Settings → Export all workspace content). HTML is the only structurally viable format for migrating entire workspaces to platforms like Confluence, while PDF is strictly for static snapshotting. For programmatic access, the official Notion API lacks a dedicated /export endpoint; developers must instead retrieve raw JSON block trees and build custom translation layers. Organizations facing rate limits (3 requests per second) or massive workspaces must implement exponential backoff engineering or use dedicated migration service providers to automate bulk extraction and format conversion.

Info

Scope of Advice & Calibration

Target Environment: This guide covers Notion workspace export capabilities, API endpoints, JSON block mapping, and third-party tooling architecture.

Target Audience: Data Engineers, Technical Project Managers, and System Administrators tasked with extracting data for backups, reporting, or cross-platform migrations.

Methodology: The formatting behaviors, API rate limits, and block-to-macro mapping logic documented here are synthesized from official Notion Developer documentation, Atlassian migration specifications, and verified enterprise engineering patterns.

Getting your data into Notion is seamless. Getting it out requires a deliberate architectural strategy.

Because Notion treats every piece of text, image, and database row as an individual "block" rather than a standard document page, exporting that data forces a translation process. If you blindly export a workspace without understanding how those blocks convert, you will break your database relations, lose your nested page hierarchies, and corrupt your formatting.

Here is the definitive guide to extracting your Notion data, whether you are exporting a single page or engineering a pipeline to pull 50,000 workspace nodes.

Section 1: The Notion Export Strategy Matrix

Before clicking any buttons or writing any scripts, you must align your business goal with the correct extraction architecture. Using the wrong method guarantees data degradation.

Business Goal Recommended Export Method Architectural Rationale
Cold Data Backup Markdown + CSV (Native) Lightweight plain-text storage. Highly portable to basic editors like Obsidian or local file systems.
Static Document Sharing PDF (Native / Browser Print) Locks visual formatting for external client reports, invoices, or resumes. Discards interactivity.
Migration to Confluence / Wikis HTML (Native) Preserves the parent-child page hierarchy via index files and maintains relative image routing.
Developer Automation / CI/CD API Block Extraction Allows programmatic querying of specific databases without manual UI intervention.
Enterprise Cross-Platform Migration Dedicated Migration Service Bypasses UI timeouts and handles JSON-to-Macro translation for complex relational databases at scale.

Section 2: Native Workspace Export

Before diving into API-based approaches, it is worth covering the most common first step: Notion's built-in full workspace export.

To export your entire workspace:

  1. Open Settings & members in the sidebar.
  2. Navigate to the Settings tab.
  3. Scroll down and click Export all workspace content.
  4. Choose your format: Markdown & CSV, HTML, or PDF.
  5. Notion will email you a download link containing a ZIP archive of your workspace.
Warning

What breaks in a workspace export:

  • Database relations and rollups are flattened. Relation properties export as plain text references rather than live links. Rollup values export as their computed result at the time of export, not as formulas.
  • Formulas export as their computed values, not the underlying formula logic.
  • Linked database views export as separate CSV files, disconnected from their source database.
  • Uploaded files and images are included in the ZIP archive, but externally linked/embedded content (e.g., images hosted on third-party services) may break if the source URLs change or expire.
  • Synced blocks export as static copies — the sync relationship is lost.

This native export is sufficient for simple backups, but it silently degrades complex data structures. If your workspace relies heavily on relations, rollups, or linked databases, you need to understand these limitations before assuming your export is complete.

Section 3: The PDF Dilemma & Architectural Workarounds

If you browse developer forums, you will see a recurring complaint: Notion's native PDF export often looks terrible. Tables get cut off, images break across pages, and custom fonts reset.

This happens because Notion does not use standard A4/Letter pagination in its web app; it is an infinite canvas. When you force an infinite canvas into a rigid PDF boundary, the rendering engine guesses where to cut the page.

The HTML-to-Print Workaround:

If you need a pixel-perfect PDF and the native exporter fails, use this sequence:

  1. Export the specific Notion page as HTML.
  2. Unzip the downloaded file and open the .html document directly in your web browser (Chrome/Edge/Safari).
  3. Use your browser's native Print to PDF function (Ctrl/Cmd + P).
  4. Adjust the scaling and margins in the browser print dialogue. This leverages the browser's rendering engine, which handles dynamic CSS tables and block layouts much better than Notion's internal PDF engine.

Section 4: Developer's Deep Dive: The Notion Export API Architecture

If you are a developer looking to automate your backups or migrations, you will quickly discover a frustrating reality: There is no POST /export endpoint in the Notion API.

You cannot hit an endpoint and receive a clean Markdown or HTML file. The API is strictly a data-retrieval system returning raw JSON. To "export" a page, you must build a custom extraction and translation pipeline.

API Permissions & Access Scoping

Before writing any code, you need to configure your Notion integration with the correct capabilities. In the Notion Integrations dashboard, your integration must have:

  • Read content capability enabled to retrieve page and block data.
  • Access explicitly granted to each page or database you intend to export (Notion integrations cannot access content unless a user shares it with the integration via the "Connect to" menu).

Workspace admin-level integrations can be granted broader access, but member-level integrations are scoped only to content explicitly shared with them. If your export pipeline is returning empty results for pages you know exist, permissions scoping is almost always the cause.

Info

The API Extraction Pipeline Architecture:

[Notion Workspace]

[API Block Retrieval: GET /v1/blocks/{block_id}/children]

[Raw JSON Tree Stored in Memory]

[Translation Layer: Block-to-Macro Mapping Logic]

[Target Output: HTML / Markdown / Confluence XML]

Minimal Python Example: Recursive Block Retrieval

The following script demonstrates authenticated block retrieval with recursive child fetching, pagination handling, and basic exponential backoff:

import requests
import time
 
NOTION_TOKEN = "your_integration_token"
HEADERS = {
    "Authorization": f"Bearer {NOTION_TOKEN}",
    "Notion-Version": "2022-06-28",
    "Content-Type": "application/json",
}
 
def fetch_blocks(block_id, retry_delay=1):
    """Recursively fetch all child blocks with pagination and backoff."""
    blocks = []
    cursor = None
 
    while True:
        url = f"https://api.notion.com/v1/blocks/{block_id}/children?page_size=100"
        if cursor:
            url += f"&start_cursor={cursor}"
 
        response = requests.get(url, headers=HEADERS)
 
        if response.status_code == 429:
            wait = retry_delay
            print(f"Rate limited. Waiting {wait}s...")
            time.sleep(wait)
            retry_delay = min(retry_delay * 2, 60)  # Exponential backoff, cap at 60s
            continue
 
        response.raise_for_status()
        data = response.json()
        retry_delay = 1  # Reset backoff on success
 
        for block in data.get("results", []):
            blocks.append(block)
            if block.get("has_children"):
                block["children"] = fetch_blocks(block["id"])
 
        if not data.get("has_more"):
            break
        cursor = data.get("next_cursor")
 
        time.sleep(0.35)  # Stay under 3 req/sec
 
    return blocks
 
# Usage: pass a page ID to retrieve its full block tree
page_blocks = fetch_blocks("your_page_id_here")

This is a minimal starting point. A production pipeline would add structured logging, persistent state for resuming interrupted exports, and a proper job queue.

The Translation Layer: Block Mapping

When you pull data via the API, you must write a script that iterates through the JSON and translates Notion's specific block types into your target format. If you are migrating to Confluence, your translation mapping should look like this:

Notion JSON Block Type Confluence HTML/Macro Equivalent Translation Complexity
heading_1, heading_2 <h1>, <h2> standard HTML tags Low
to_do Confluence Task List Macro <ac:task-list> Medium (Requires XML syntax)
child_database Page Properties Macro / Static HTML Table High (Requires relational mapping)
synced_block Excerpt Macro / Excerpt Include Macro High (Requires tracking source block IDs)
toggle Confluence Expand Macro <ac:structured-macro> Medium

Section 5: Engineering Guidance: Handling API Rate Limits

When an enterprise organization needs to programmatically export a large workspace, amateur scripts fail quickly. The Notion API enforces a strict rate limit of 3 requests per second. If you recursively fetch nested pages without precise throttling, your IP will be blocked with HTTP 429 Too Many Requests errors.

To put this in perspective: if a page averages 15 blocks and each requires a child-block fetch, a 10,000-page workspace needs roughly 20,000+ API calls. At 3 requests per second (assuming no retries), that is approximately 1.8 hours of continuous API access — and real-world backoff and retry overhead can double or triple that.

To build a resilient export pipeline, you must implement the following engineering patterns:

  1. Exponential Backoff Strategy: When your script hits a 429 error, do not retry immediately. Implement a delay that multiplies after each failure (e.g., Wait 2 seconds -> Wait 4 seconds -> Wait 8 seconds). See the Python example above for a working implementation.
  2. Request Queuing: Do not use simple loops (for each block in page). Use a robust job queue (like Redis or RabbitMQ) to manage API calls, ensuring you never exceed the 3 req/sec concurrency limit.
  3. Pagination Handling: The API limits responses to 100 blocks per request. You must actively parse the has_more: true flag and pass the next_cursor string into your subsequent API calls to prevent data truncation.

Section 6: The Tooling Ecosystem

Because writing a custom JSON parser and managing rate limits is highly resource-intensive, a diverse ecosystem of export tools has emerged. You need to evaluate these tools based on scale and reliability.

Tier 1: Open-Source Scripts & Browser Extensions

  • Examples: notion-exporter (NPM), notion-backup, notion2md, Notion Exporter Chrome Extension.
  • Scale Threshold: Best suited for smaller workspaces.
  • Reliability: Low to Medium. Browser extensions rely on UI scraping and break when Notion updates its frontend. Open-source CLI tools often lack robust retry logic for API timeouts, though actively maintained projects like notion-backup provide scheduled export automation.
  • Best For: Solo developers and small startup backups.

Tier 2: iPaaS Sync Tools

  • Examples: Unito, Zapier, Make.com.
  • Scale Threshold: Best suited for ongoing record-level syncs rather than full workspace exports.
  • Reliability: Medium. Excellent for syncing specific task boards or sending individual database rows to Google Sheets. However, they struggle to export deep, nested page hierarchies or migrate entire wikis structurally.
  • Best For: Ongoing cross-departmental workflows (e.g., syncing a Notion product roadmap to Jira issues).

Tier 3: Dedicated Migration Services

  • Examples: Clone Partner, and other specialized migration consultancies.
  • Scale Threshold: Large and enterprise-scale workspaces.
  • Reliability: High. These providers use dedicated infrastructure with built-in token bucket rate limiting, exponential backoff, and custom translation layers. They programmatically map Notion JSON blocks (like relations and rollups) directly into target platform structures such as Confluence macros.
  • Best For: Enterprise environments requiring compliant, zero-downtime cross-platform migrations where data degradation is unacceptable.
Info

Disclosure: Clone Partner is a dedicated migration service provider. We have direct experience with the Notion export challenges described in this guide, which informs the technical recommendations above. Where we reference our own services, we do so transparently.

Sources & References

To verify the API limits, translation architectures, and export behaviors discussed in this guide, refer to the following official documentation and developer resources:

Frequently Asked Questions

Is there a programmatic way to export Notion to PDF via the API?
No. The official Notion API returns raw JSON data, not formatted files. To automate PDF generation, you must retrieve the JSON data, pass it through a Markdown/HTML converter, and then use a separate PDF rendering library (like Puppeteer) to generate the final file.
How do I avoid HTTP 429 errors when exporting Notion data?
You must throttle your API calls to stay under the limit of 3 requests per second. Implement an exponential backoff algorithm in your code to automatically pause and retry requests when the Notion server returns a rate limit error.
Do Notion databases export as CSV files?
Yes, if you select the "Markdown & CSV" export option in the UI. The database itself will export as a CSV file containing properties as columns, while the content inside each database page will export as individual Markdown files.
How does the Notion API handle synced blocks during extraction?
The API returns a synced_block object containing a reference to the original_synced_block_id. If you are migrating this data to a platform like Confluence, your script must track these IDs and translate them into equivalent macros (like Excerpt/Excerpt Include) to maintain the sync logic.
Are Notion Exporter templates reliable for bulk exports?
Notion templates labeled as "Export Compatible" (like specific Resume templates) are designed with strict block structures to prevent pagination breaks when using the native PDF export. They are highly reliable for static, single-page documents but do not help with bulk workspace extraction or API routing.

More from our Blog