Blog

How to Access Notion Data Without the Official API

Learn how to access Notion pages, databases, and workspace data through shadow APIs discovered from browsing traffic — no official API integration or token setup required.

Lewis Tham
April 3, 2026

How to Access Notion Data Without the Official API

Notion has become the knowledge base of choice for startups, engineering teams, and individual creators. Its flexible database system, nested pages, and rich content blocks make it a powerful tool for organizing information. But getting data out of Notion programmatically is more complicated than it should be.

Notion's official API launched in 2021 and has improved significantly, but it still has major limitations. It requires creating an integration, sharing specific pages with it, handling OAuth for workspace access, and dealing with a block-based data model that requires multiple API calls to reconstruct a single page. The API does not support all block types, has pagination limits, and rate-limits aggressively at 3 requests per second.

Notion's own web app does not use the public API. It uses a separate, more capable internal API that returns complete page trees, supports all block types, and handles real-time collaboration. These shadow APIs are what Unbrowse discovers.

What Are Shadow APIs?

Shadow APIs are the undocumented internal HTTP endpoints that web applications use to load data for their frontend. Every modern web app has them — they are the real data layer, while the public API is a curated subset.

When you open a Notion page in your browser, the client fires requests to:

  • A page load endpoint that returns the full block tree for a page in a single call
  • A database query endpoint that returns filtered and sorted rows with all properties
  • A search endpoint that searches across your entire workspace
  • A space endpoint that returns workspace metadata, members, and settings
  • A collection endpoint that returns database schemas and views
  • A file endpoint that returns signed URLs for uploaded files and images

These endpoints handle everything the official API does and more — inline databases, synced blocks, template buttons, relation rollups — all in their native format.

What Unbrowse Discovers on Notion

Unbrowse captures all HTTP traffic during a browsing session and indexes the API routes. When you browse your Notion workspace through Unbrowse, it discovers:

  • Page content endpoints — full page block trees including all nested content, comments, and metadata
  • Database query endpoints — the internal query API that supports all filter types, sorts, and aggregations
  • Search endpoints — workspace-wide search that returns pages, databases, and blocks matching a query
  • User and space endpoints — workspace members, permissions, and settings
  • Collection endpoints — database schemas, views, and view configurations
  • Transaction endpoints — the operation log that powers Notion's real-time sync
  • File upload endpoints — signed S3 URLs for images and file attachments

Each endpoint is cataloged with its URL, request format, authentication headers, and response schema.

Getting Started

Install Unbrowse:

npm install -g unbrowse

Browse your Notion workspace to discover its internal APIs:

unbrowse browse "https://www.notion.so/your-workspace/your-page-id"

Unbrowse opens a real browser with your Notion session, captures the API traffic, and indexes every endpoint.

Resolve a discovered endpoint:

unbrowse resolve "notion page content"

Execute the route:

unbrowse execute "notion page content" --params '{"pageId": "abc123def456"}'

Code Example: Notion Knowledge Extractor

Here is a Node.js script that extracts all pages from a Notion database for use in an AI pipeline:

import Unbrowse from 'unbrowse';

const unbrowse = new Unbrowse();

// Resolve Notion endpoints from discovered skills
const dbSkill = await unbrowse.resolve('notion database query');
const pageSkill = await unbrowse.resolve('notion page content');

// Query a database for all rows
const rows = await unbrowse.execute(dbSkill, {
  databaseId: 'your-database-id',
  filter: { property: 'Status', select: { equals: 'Published' } },
  sorts: [{ property: 'Created', direction: 'descending' }]
});

// Extract full content for each page
for (const row of rows.results) {
  const page = await unbrowse.execute(pageSkill, {
    pageId: row.id
  });

  const title = row.properties.Name.title[0]?.plain_text;
  const blocks = page.recordMap.block;
  const textContent = Object.values(blocks)
    .filter(b => b.value?.type === 'text')
    .map(b => b.value.properties?.title?.[0]?.[0])
    .join('\n');

  console.log(`## ${title}`);
  console.log(textContent.slice(0, 200) + '...');
}

This gives you access to the full block tree — including block types the official API does not support.

Performance Comparison

Method Setup Time Avg Response Time Full Block Support Rate Limit
Notion Official API 15-30 min 300-600ms Partial 3 req/sec
Notion SDK (unofficial) 10-20 min 300-600ms Partial 3 req/sec
HTML Scraping Not practical N/A N/A N/A
Unbrowse (Shadow API) 2 minutes 100-400ms Yes (all blocks) Higher

Notion's web client uses a different API than the public one. The internal API returns complete page trees in a single request, supports all block types, and has more generous rate limits because it is designed to support real-time editing.

Why the Internal API Is More Capable

Notion's official API was built as a clean, stable interface for third-party integrations. It deliberately omits complex block types, limits query depth, and paginates aggressively. The internal API has none of these restrictions because Notion's own frontend needs the full data.

Specific advantages of the internal API:

  • Single-request page loads — the official API requires recursive calls to load nested blocks; the internal API returns the full tree
  • All block types — synced blocks, template buttons, inline databases, toggle headings, and more
  • Real-time data — the internal API supports Notion's operational transform system for live collaboration
  • Bulk operations — query multiple pages or databases in fewer calls

FAQ

Is this legal? Unbrowse accesses the same API endpoints your browser uses when you view Notion pages. It does not bypass authentication or access data you do not have permission to see. Review Notion's Terms of Service for your specific use case.

Do I need a Notion account? Yes. Notion pages are not public by default. You need to be logged into your Notion workspace in the Unbrowse browser session to access your data.

How does authentication work? Unbrowse captures your session cookies and authentication headers during the browse step. These are stored locally and reused for API calls. Notion sessions typically last for weeks before requiring re-authentication.

Can I write data back to Notion? The internal API supports write operations, but Unbrowse is designed primarily for read access. For creating and updating pages, the official Notion API is the safer choice.

What about Notion's rate limits? The internal API has higher rate limits than the public API, but they still exist. Unbrowse caches route definitions so you can make targeted calls without unnecessary overhead.