DEV Community

Nico Reyes
Nico Reyes

Posted on

API docs said pagination worked. It didn't.

API docs said pagination worked. It didn't.

Was integrating this ecommerce API last week for product data. Docs say pagination works with offset and limit parameters. Seemed simple enough.

What the docs showed

response = requests.get(
    'https://api.example.com/products',
    params={'offset': 0, 'limit': 100}
)
Enter fullscreen mode Exit fullscreen mode

Perfect right? Just loop and increment offset by 100 each time.

The problem

Worked fine for first 200 products maybe 300. Then started getting duplicates. Then missing products entirely. Offset 400 returned same stuff as offset 300. Offset 1000 gave me products from offset 200.

Thought my code was broken. Checked logs for 2 hours. Nothing wrong on my end.

Turns out

API was sorting by relevance not ID. Every time I hit it the order changed slightly because products got sold or restocked. So offset 400 wasnt actually the 400th product anymore, it was whatever happened to be 400th at that exact moment.

Docs never mentioned this. Support didnt know either when I asked.

What actually worked

Had to switch to cursor based pagination. Most APIs support this but dont document it well.

import requests

url = 'https://api.example.com/products'
all_products = []
cursor = None

while True:
    params = {'limit': 100}
    if cursor:
        params['cursor'] = cursor

    response = requests.get(url, params=params)
    data = response.json()

    all_products.extend(data['products'])

    cursor = data.get('next_cursor')
    if not cursor:
        break

print(f'Got {len(all_products)} products total')
Enter fullscreen mode Exit fullscreen mode

Cursor is basically a bookmark. API returns next_cursor in response and you pass it back in next request. Guarantees you get unique results even if data changes between requests.

If you see duplicate items across pages your offset pagination is probably broken. Check response for next_cursor or continuation_token or page_token. Most REST APIs have this but call it different things. Sometimes just trying cursor as a param works even if docs dont mention it.

Wasted 4 hours on this because docs looked fine. Still annoyed their docs showed offset as the main example tho.

Top comments (0)