Notion Search API无法返回账号全部页面ID问题求助
我正在开发一款基于Notion API的应用,目标是获取账号下所有页面ID。我已经实现了递归函数处理POST https://api.notion.com/v1/search的分页机制,会一直请求直到没有下一页,但奇怪的是每次调用得到的结果数量每天都在变:上个月能拿到约250个页面ID,昨天只拿到71个,但我确定账号里的页面远不止这些。
编辑1:
最近几天运行代码又拿到了200+结果,之前猜测的“只能检索近三个月页面”已经排除,现在完全找不到原因。
附上我的代码:
import axios from 'axios'; import dotenv from 'dotenv'; import os from 'os'; const notion = new Client({ auth: NOTION_TOKEN, }); // 获取UID列表(递归分页) const fetchListOfUids = async (nextPageId, blockList = []) => { const payload = nextPageId ? { start_cursor: nextPageId } : {}; try { const { results, has_more, next_cursor } = await notion.search({ ...payload, }); const accumulatedBlockList = [...blockList.concat(results)]; // 有下一页则继续请求 if (has_more) { return fetchListOfUids(next_cursor, accumulatedBlockList); } return accumulatedBlockList; } catch (err) { console.log({ err }); } }; // 主函数 (async () => { createDownloadDirectory(); try { const blockList = await fetchListOfUids(); blockList.map(async (block) => { setTimeout(async () => { await downloadAsMarkdown(block); }, 1000); }); } catch (err) { console.log({ err }); } })();
可能的原因及解决方案
1. 默认过滤规则导致结果不全
Notion的search端点默认只会返回可搜索范围内的内容,以下情况会导致页面被过滤:
- 页面在回收站(未彻底删除的回收站内容默认不参与搜索)
- 集成token无该页面访问权限(比如页面权限被修改、共享链接过期)
- 页面属于数据库深层条目,默认搜索未遍历到
解决办法:
在搜索请求中添加明确的过滤和排序规则,锁定页面类型并固定排序逻辑,避免结果波动:
await notion.search({ ...payload, filter: { property: "object", value: "page" // 只搜索页面类型 }, sort: { direction: "ascending", timestamp: "created_time" // 固定排序规则,防止分页漏项 } });
2. 递归分页的稳定性问题
递归逻辑本身没问题,但API偶发的延迟或网络波动可能导致has_more/next_cursor返回不准确,中断后续请求;另外递归出错时无重试机制,会直接终止获取流程。
解决办法:
换成循环实现分页,同时添加日志和重试逻辑,便于排查问题:
const fetchListOfUids = async () => { const blockList = []; let nextPageId = null; do { try { const { results, has_more, next_cursor } = await notion.search({ start_cursor: nextPageId, filter: { property: "object", value: "page" } }); blockList.push(...results); nextPageId = has_more ? next_cursor : null; console.log(`本次获取${results.length}条,累计${blockList.length}条`); } catch (err) { console.error(`请求失败,2秒后重试:`, err); await new Promise(resolve => setTimeout(resolve, 2000)); } } while (nextPageId); return blockList; };
3. API限流导致部分请求失效
Notion API有速率限制(每秒最多3次请求,每分钟最多1000次),如果请求频率过高,会被临时限流,导致部分请求返回空结果或不完整分页数据。
解决办法:
在分页请求之间添加固定延迟,避免触发限流:
// 在每次搜索请求后添加延迟 await new Promise(resolve => setTimeout(resolve, 500));
同时可以检查响应头的X-RateLimit-Remaining字段,实时监控剩余请求额度。
4. Notion搜索索引更新延迟
Notion的搜索索引不是实时同步的,页面创建、修改后可能需要一段时间才能被API搜索到;部分空页面或含大量嵌入内容的页面也可能被标记为不可搜索,导致不同时间点结果数量波动。
解决办法:
- 手动在Notion客户端搜索,对比API返回结果,确认是否存在客户端能搜到但API搜不到的页面
- 在搜索请求中添加
query: ""空查询,强制返回所有可搜索页面
内容的提问来源于stack exchange,提问作者Andy Lu

