Search results are returned one page at a time. Instead of asking for a page number, you follow a cursor — a token that points to the next page. This keeps paging fast and consistent even while new photos are being added.

The pagination object

Every list response includes a pagination object next to your data:

Fetching the next page

  1. Make your search as usual.
  2. Read pagination.next_cursor from the response.
  3. Repeat the same request, adding cursor=<next_cursor>.
  4. Stop when has_more is false (at that point next_cursor is null).
Here is the same loop in Python:
Keep your query the same between pages. The cursor already remembers your search text and filters, so you only need to add cursor. Set per_page on the first request; following pages keep that same page size.
Cursors are short-lived — they stay valid for about 5 minutes. If a cursor expires (or you change the query), simply start again from the first page without a cursor.

Which endpoints paginate?

Three search endpoints support cursor pagination:
  • Search photos by textGET /api/v1/search/photos
  • Search photos by imagePOST /api/v1/search/photos
  • Find similar photosGET /api/v1/photos/{photo_id}/similar
They all work the same way: read pagination.next_cursor and pass it back as cursor to get the next page, stopping when has_more is false. (On some plans the number of similar photos is capped to a single page — in that case has_more is false from the start.)
For image search, you only upload the image on the first request. To get the next page, send the request again with just cursor=<next_cursor> — no need to re-upload the image. The cursor already remembers your image and filters.
The other endpoints return a single response and do not take a cursor: facets, collections and usage return their full list directly.