How to handle pagination when querying Notion database API

I’m working with the Notion API to fetch data from a database that has more than 100 entries. I’m trying to use pagination but I keep getting the same results from the first page even when I include the cursor parameter.

Here’s my current API call:

curl -X POST 'https://api.notion.com/v1/databases/DATABASE_ID/query' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Notion-Version: 2021-05-13' \
  -H 'Content-Type: application/json' \
  --data '{
    "filter": {},
    "start_cursor": "CURSOR_VALUE_HERE"
  }'

The response always shows the first batch of results instead of continuing from where the previous request left off. What am I doing wrong with the pagination implementation? Should I be structuring the request differently to properly iterate through all pages of results?

had similar headaches with this - double check you’re actually grabbing the next_cursor from the response correctly. sometimes its nested weird in the json and easy to miss. also make sure your not hardcoding the cursor value, it needs to be dynamic from each response

The issue you’re experiencing usually stems from improper cursor handling between requests. When I was building an integration that needed to process thousands of Notion pages, I discovered that the cursor value must be extracted from the exact response object and used immediately in the next call without any modifications. One common mistake is storing the cursor in a variable that gets overwritten or corrupted before the next API call. Another thing to verify is that your database actually has more than 100 entries - you can confirm this by checking if the has_more field returns true in your initial response. If it returns false, there simply aren’t enough entries to paginate. Also ensure you’re making the subsequent requests in the correct sequence without any parallel processing, as cursors are session-specific and can become invalid if not used properly.

I encountered this exact issue when working on a project that needed to sync large Notion databases. The problem is likely that you’re using an invalid or expired cursor value in your start_cursor parameter. When you make your first request without any cursor, check the response body for the next_cursor field at the bottom of the JSON response. This value should be used as your start_cursor in the subsequent request - not any arbitrary cursor value. The cursor is essentially a token that tells Notion where to continue reading from. Also worth noting that if has_more is false in the response, you’ve reached the end and shouldn’t make another request. I made the mistake of continuing to paginate even when there were no more results, which caused unnecessary API calls. Make sure you’re properly checking this boolean field before attempting the next page.