To retrieve more than 50,000 items from our premium endpoints (such as Get Artists or Get Songs), you must transition from Offset-based pagination to Cursor-based pagination.
What is a cursor ?
A cursor is essentially a bookmark. While an offset tells the API how many rows to skip, a cursor acts as a direct pointer to a specific record. This allows you to "unlock" the next set of results without hitting the performance walls of high offsets.
The endpoints that require it include a cursor in the "page" section of the response.
Depending on your performance needs, you can implement one of two strategies:
1. Sequential Fetching (simpler, slower)
In this linear approach, you fetch one page at a time. Best for simple scripts or small-to-medium datasets.
The Flow: Request Page A -> Extract
cursorfrom the response -> Request Page B using that cursor.
2. Hybrid Parallel Fetching (high performance)
This is the fastest way to ingest massive datasets. You can combine cursors with offsets to bypass the 50k limit while maintaining parallel processing speed, within the limit of 5k calls/minute.
Phase 1: Fetch the first 50,000 items in parallel using
offset(0 to 49,900).
Phase 2: Capture the
cursorfrom the last item of that 50,000-item batch.
Phase 3: Start a new parallel batch. Pass the new
cursorand reset your offset to 0. This "unlocks" the next 50,000 items.
Note : If you are using the Python SDK, this process is handled for you.
Let's take an example
Say you want to use the Get Artists endpoint to retrieve the (at time of writing) 140,830 artists with more than 10,000 Spotify followers.
1. Sequentially
Your first CURL request is the following:
curl -X POST "https://customer.api.soundcharts.com/api/v2/top/artists?offset=0&limit=100" \
-H "x-app-id: YOUR_APP_ID" \
-H "x-api-key: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sort": {"platform": "spotify","metricType": "followers","period": "month","sortBy": "total","order": "desc"},"filters": [{"type": "metric","data": {"platform": "spotify","metricType": "followers","min": "10000","max": "100000000000"}}]}'
In the "page" section of the request, you find the following cursor:
"cursor": "eyJpZFZhbHVlIjoiMTMxNDAyOCIsImZpZWxkVmFsdWUiOjI0MTYxMjQyLCJvcmRlciI6ImRlc2MiLCJtZXRyaWMiOnRydWUsInBsYXRmb3JtIjoic3BvdGlmeSIsIm1ldHJpY1R5cGUiOiJmb2xsb3dlcnMiLCJwZXJpb2QiOiJtb250aCIsInNvcnRCeSI6InRvdGFsIn0="
You can then pass it in the next call to retrieve the next page, without changing the offset:
curl -X POST "https://customer.api.soundcharts.com/api/v2/top/artists?offset=0&limit=100&cursor=eyJpZFZhbHVlIjoiMTMxNDAyOCIsImZpZWxkVmFsdWUiOjI0MTYxMjQyLCJvcmRlciI6ImRlc2MiLCJtZXRyaWMiOnRydWUsInBsYXRmb3JtIjoic3BvdGlmeSIsIm1ldHJpY1R5cGUiOiJmb2xsb3dlcnMiLCJwZXJpb2QiOiJtb250aCIsInNvcnRCeSI6InRvdGFsIn0%3D" \
-H "x-app-id: YOUR_APP_ID" \
-H "x-api-key: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sort": {"platform": "spotify","metricType": "followers","period": "month","sortBy": "total","order": "desc"},"filters": [{"type": "metric","data": {"platform": "spotify","metricType": "followers","min": "10000","max": "100000000000"}}]}'
Retrieve the cursor, pass it in the next call, and so on!
2. In parallel
Retrieve the first 50,000 results in parallel by playing with the offset.
On the last page (the one with offset 49,900), you'll retrieve a cursor like this one :
"cursor": "eyJpZFZhbHVlIjoiMTQ5NDU5NSIsImZpZWxkVmFsdWUiOjQ2MjA2LCJvcmRlciI6ImRlc2MiLCJtZXRyaWMiOnRydWUsInBsYXRmb3JtIjoic3BvdGlmeSIsIm1ldHJpY1R5cGUiOiJmb2xsb3dlcnMiLCJwZXJpb2QiOiJtb250aCIsInNvcnRCeSI6InRvdGFsIn0="
You can then pass it in the next batch of call, and start anew with offsets from 0 to 49,900 :
curl -X POST "https://customer.api.soundcharts.com/api/v2/top/artists?offset=0&limit=100&cursor=eyJpZFZhbHVlIjoiMTQ5NDU5NSIsImZpZWxkVmFsdWUiOjQ2MjA2LCJvcmRlciI6ImRlc2MiLCJtZXRyaWMiOnRydWUsInBsYXRmb3JtIjoic3BvdGlmeSIsIm1ldHJpY1R5cGUiOiJmb2xsb3dlcnMiLCJwZXJpb2QiOiJtb250aCIsInNvcnRCeSI6InRvdGFsIn0%3D" \
-H "x-app-id: YOUR_APP_ID" \
-H "x-api-key: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sort": {"platform": "spotify","metricType": "followers","period": "month","sortBy": "total","order": "desc"},"filters": [{"type": "metric","data": {"platform": "spotify","metricType": "followers","min": "10000","max": "100000000000"}}]}'
On the last page, you'll retrieve a new cursor, and so on.