A tiny local server + CLI that lets you talk to Notion's private API β including Notion AI β from your terminal, scripts, or curl.
It runs entirely on your machine, uses your own Notion login, and ships as a single file (notionproxy.js). No build step, no dependencies to install.
# ask Notion AI from your terminal
bun notionproxy.js ai "explain recursion in one sentence"
# or run the HTTP server and use curl
bun notionproxy.js
curl -X POST http://127.0.0.1:3000/ai \
-H "Content-Type: application/json" \
-d '{"prompt":"explain recursion in one sentence"}'Heads-up: This talks to Notion's internal API (
/api/v3), which is undocumented and not officially supported. It's great for personal use and tinkering, but Notion could change it at any time. Use it on your own account.
- What you can do with it
- Requirements
- Setup (step by step)
- Quick start
- The
aiCLI - HTTP API reference
- Choosing a model
- Configuration (
.env) - What's in this repo
- Troubleshooting
- Security & privacy
- π¬ Ask Notion AI questions (one-shot or an interactive chat that remembers the conversation).
- π Optionally let the AI search the web.
- π§ Pick any model your account has (Claude, GPT, Gemini, Grok, and more) using friendly names like
claude-opus-4.8. - π‘ Stream answers as they're generated (Server-Sent Events).
- π Read Notion pages and list your workspaces.
- π Send raw requests to any
/api/v3endpoint (for power users).
-
Bun (a fast JavaScript runtime). Install it once:
# macOS / Linux curl -fsSL https://bun.sh/install | bash # Windows (PowerShell) powershell -c "irm bun.sh/install.ps1 | iex"
Check it works:
bun --version -
A Notion account (the AI features need a workspace where Notion AI is enabled).
-
A Chromium browser (Chrome, Edge, Braveβ¦) to grab your login token with the included extension β or you can copy the cookie manually.
Clone or download this repo. You only need two things to run it: notionproxy.js and your own .env.
The proxy logs in as you using a browser session cookie called token_v2. The easiest way to get it is the one-click extension included in this repo.
Using the extension (recommended):
-
Open your browser's extensions page:
chrome://extensions(oredge://extensions). -
Turn on Developer mode (toggle, usually top-right).
-
Click Load unpacked and select the
extension/folder in this project. -
Make sure you're logged in at notion.so in that browser.
-
Click the "Notion Proxy Credentials" extension icon β Copy .env.
-
It copies something like:
NOTION_TOKEN_V2=v02%3A... NOTION_USER_ID=00000000-0000-0000-0000-000000000000
The extension only reads your cookies locally. Nothing is sent anywhere except Notion itself.
Manual alternative: open notion.so β DevTools β Application β Cookies β copy the value of token_v2.
cp .env.example .envOpen .env and paste your token (and user id if you have it):
NOTION_TOKEN_V2=v02%3A... # required
NOTION_USER_ID=... # recommended (the extension fills this in)
# NOTION_SPACE_ID=... # optional: pin a specific workspaceThat's it β you're ready. notionproxy.js auto-loads .env from the current folder.
Option A β the CLI (simplest):
bun notionproxy.js ai "write a haiku about the sea"Option B β the HTTP server:
bun notionproxy.js
# β [notionproxy] listening on http://127.0.0.1:3000Then in another terminal:
# is my token working?
curl http://127.0.0.1:3000/health
# ask the AI
curl -X POST http://127.0.0.1:3000/ai \
-H "Content-Type: application/json" \
-d '{"prompt":"give me 3 productivity tips"}'Run bun notionproxy.js ai <command>. If you don't pass a known command, your words are treated as the prompt.
| Command | What it does |
|---|---|
bun notionproxy.js ai "your question" |
Ask a one-shot question |
bun notionproxy.js ai chat |
Interactive chat that remembers the session |
bun notionproxy.js ai models |
List every model your account can use |
bun notionproxy.js ai spaces |
List your workspaces and whether Notion AI is available |
bun notionproxy.js ai whoami |
Show which account the token belongs to |
Flags:
| Flag | Meaning | Example |
|---|---|---|
--model <id> |
Pick a model | --model claude-opus-4.8 |
--web |
Let the AI search the web | --web |
--space <id> |
Use a specific workspace | --space 1234abcd-... |
Examples:
bun notionproxy.js ai --model gpt-5.5 "summarize the theory of relativity"
bun notionproxy.js ai --web "what shipped in the latest TypeScript release?"Interactive chat supports in-session commands:
bun notionproxy.js ai chat
you> /model grok-4.3 # switch model
you> /web on # turn on web search
you> /reset # forget the conversation
you> /quit # exit
Start the server with bun notionproxy.js. Base URL (default): http://127.0.0.1:3000
Checks that your token is valid.
curl http://127.0.0.1:3000/health
# { "ok": true, "notionStatus": 200 }Lists available models with friendly ids.
curl http://127.0.0.1:3000/modelsLists your workspaces and account record (raw Notion getSpaces).
Loads a Notion page by id.
curl http://127.0.0.1:3000/page/1234abcd5678ef901234abcd5678ef90Ask Notion AI. Body fields (only prompt is required):
| Field | Type | Description |
|---|---|---|
prompt |
string | required β your question |
model |
string | model id / name / codename (see below) |
web |
boolean | enable web search |
space |
string | workspace id to use |
stream |
boolean | stream the reply as it's generated |
Normal (one JSON reply):
curl -X POST http://127.0.0.1:3000/ai \
-H "Content-Type: application/json" \
-d '{"prompt":"what is 2+2?","model":"claude-opus-4.8"}'{
"reply": "2 + 2 = 4.",
"model": { "id": "claude-opus-4.8", "name": "Opus 4.8", "family": "anthropic", "codename": "ambrosia-tart-high", "default": false },
"prompt": "what is 2+2?"
}Streaming (stream: true) β returns text/event-stream:
curl -N -X POST http://127.0.0.1:3000/ai \
-H "Content-Type: application/json" \
-d '{"prompt":"write a short poem","stream":true}'data: {"delta":"Waves "}
data: {"delta":"roll in slowβ¦"}
data: {"done":true,"model":{"id":"claude-opus-4.8", ...}}
(The -N flag tells curl not to buffer, so you see chunks live.)
Raw passthrough to any Notion /api/v3 endpoint β the body is forwarded as-is.
curl -X POST http://127.0.0.1:3000/v3/getSpaces \
-H "Content-Type: application/json" -d '{}'See what your account offers:
bun notionproxy.js ai modelsID NAME FAMILY CODENAME
gpt-5.5 GPT-5.5 openai opal-quince-medium
claude-opus-4.8 Opus 4.8 anthropic ambrosia-tart-high
grok-4.3 Grok 4.3 xai xigua-mochi-medium
...
You can pass a model as the friendly id (claude-opus-4.8), the display name (Opus 4.8), or Notion's raw codename (ambrosia-tart-high) β all resolve to the same model. If you omit model, a sensible default is used.
| Variable | Required | Default | Description |
|---|---|---|---|
NOTION_TOKEN_V2 |
β yes | β | Your Notion session cookie (full account access β keep secret). |
NOTION_USER_ID |
recommended | β | Your user id; some endpoints need it. |
NOTION_SPACE_ID |
no | auto | Pin a workspace. If blank, one with AI enabled is auto-selected. |
HOST |
no | 127.0.0.1 |
Network interface to bind. Keep it localhost. |
PORT |
no | 3000 |
Port to listen on. |
NOTION_CLIENT_VERSION |
no | 23.13.0.10 |
Sent as notion-client-version; bump if Notion starts rejecting. |
.
βββ notionproxy.js # the whole app β server + CLI in one file
βββ extension/ # one-click browser extension to grab your token
βββ .env.example # copy to .env and fill in
βββ README.md
Run it with bun notionproxy.js (server) or bun notionproxy.js ai "..." (CLI). No bun install needed β it has no dependencies.
| Symptom | Fix |
|---|---|
Missing NOTION_TOKEN_V2 on startup |
You haven't created .env or filled in the token. See Setup. |
/health returns ok: false / status 401 |
Your token_v2 expired. Re-grab it with the extension and update .env. |
port 3000 is in use |
Another copy is running. Stop it: lsof -ti tcp:3000 | xargs kill, or set a different PORT. |
AI replies [Notion AI unavailableβ¦] |
That workspace has no AI plan or you hit the usage limit. Try bun notionproxy.js ai spaces to find one with AI, then set NOTION_SPACE_ID. |
| "No Notion AI chats exist yet" | Open Notion, send one message to Notion AI manually, then retry (the tool reuses a real chat thread). |
NOTION_TOKEN_V2is a session cookie that grants full access to your Notion account. Treat it like a password: never commit it, never share it..envis already in.gitignore.- The server binds to
127.0.0.1(localhost) with no authentication. That's fine for personal local use. Do not changeHOSTto0.0.0.0or expose the port β anyone who could reach it would be using your Notion account. - Everything runs locally. The only outbound calls are to
notion.soitself. - This uses Notion's private API and is intended for personal use; it isn't affiliated with or endorsed by Notion.
Licensed under a modified MIT license that requires attribution: the credit
Made By VK β https://discord.gg/bnZa5uDCmV
must be kept in copies of the software and in its output (including the startup banner). See LICENSE for the full terms.