Why does the admin REST API intermittently fail to paginate all products?

I’m having issues with the pagination returned from the admin REST API

i’m trying to pull out 3738 products - but about 30% of the time it fails to get them all (not always failing at the same page) - the rest of the time it completes ok.

eg in the output from my last run below, it returned 1250 not 3738 - the previous run returned only 250

Shopify count 3738
200
page_info=eyJsYXN0X2lkIjozODQ4NTQxMDc3NTM4LCJsYXN0X3ZhbHVlIjoiQXRsYXMgVW5kZXJiZWQgU3RvcmFnZSBEcmF3ZXIiLCJkaXJlY3Rpb24iOiJuZXh0In0>; rel="next"
200
page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6NDgwMTY5Mjg2MDQ1MCwibGFzdF92YWx1ZSI6IkJvc3RvbiBPdXRkb29yIFN1biBMb3VuZ2VyIGFuZCBTaWRlIFRhYmxlIC0gR3VubWV0YWwgR3JleSJ9>; rel="next"
200
page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6Mzg0ODM0MTQ4NzY1MCwibGFzdF92YWx1ZSI6IkNvYXN0IERpbmluZyBTdWl0ZSAyMDAwIDMgUGllY2UgLSBTdGFpbmxlc3MifQ>; rel="next"
200
page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6ODMxNDMxMjQyNTc5NCwibGFzdF92YWx1ZSI6IkVib255IFBsdW1lIFNxdWFyZSBDdXNoaW9uIn0>; rel="next"
200
page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6ODMxNDMxMjQyNTc5NCwibGFzdF92YWx1ZSI6IkVib255IFBsdW1lIFNxdWFyZSBDdXNoaW9uIn0>; rel="next"
1250 fetched from shopify

i am getting 200 success codes returned in the header so does not appear to be a rate limit issue (and again it completes properly about 70% of the time)

does anyone have any suggestions for why it would throw an intermittent error in the pagination? Is this a known issue at the shopify end?

cheers

Still having this issue - can anyone from shopify help please?

@Shopify_77 help please…?

despite no help at all from either shopify support ticket or this forum :roll_eyes: - i have found the issue and will put it here in case it helps someone else…

it’s that the headers are returning with different link keys

Link != link

i have fixed it by running the header keys through a strtolower() to put them all in lower case first :persevering_face:

whats up with that @Shopify_77 ?

1 Like

Experienced the same issue and after hours of head scratching came to the same solution. Wish I had found this earlier..

@Shopify_77 it would be great if this was clearly stated somewhere as a update note or bug.

After hours of trying and trying again, I received Fetched 250 products. Next page: None.

Our store has almost 30k products… so… the road was long.. but here we are..

Finally retrieved > Fetched 250 products. Next page: https://store.myshopify.com/admin/api/….

The issue stemmed from the way the code was parsing the Link header returned by the Shopify API for pagination. Here’s what went wrong and how it was fixed:

  1. Parsing the Link Header: The Shopify API returns a Link header in the response when there are multiple pages of results. This header contains links to the next and previous pages. Initially, the code attempted to parse this header using the urlparse and parse_qs functions, but it didn’t handle the header correctly, resulting in errors.

  2. Incorrect Parsing Logic: The original code used urlparse to extract the URL from the Link header, but it didn’t handle the rel attribute properly. Additionally, it didn’t consider that there might be multiple links in the header. This led to incorrect extraction of the next page URL and, in some cases, the extraction failed altogether.

  3. Fixed Parsing Logic: The code was modified to split the Link header by commas and then iterate through each part to find the link with the next relation. This ensures that even if there are multiple links in the header, the correct one for the next page is selected. The correct URL is then extracted and used for the next API call.

By fixing the parsing logic to correctly handle the Link header, the code now accurately identifies the URL of the next page, enabling successful pagination through the Shopify API results.

# Function to fetch products in batches
def fetch_products_in_batches(batch_size=250):
    products = []
    next_page_url = f"{SHOP_DOMAIN}/admin/api/{API_VERSION}/products.json?limit={batch_size}"

    while next_page_url:
        response = requests.get(next_page_url, auth=(API_KEY, API_PASSWORD))
        if response.status_code == 200:
            data = response.json()

            # Extract the URL from the link header
            link_header = response.headers.get('link')
            if link_header:
                # Split the link header by commas
                links = link_header.split(',')
                for link in links:
                    parts = link.split(';')
                    url = parts[0].strip('<>')
                    rel = parts[1].split('=')[1].strip('"')
                    if rel == 'next':
                        next_page_url = url
            else:
                next_page_url = None

            products.extend(data.get('products', []))
            print(f"Fetched {len(products)} products. Next page: {next_page_url}")
        else:
            print(f"Failed to fetch products from Shopify. Error: {response.text}")
            break

    return products

Watch out for the

response.headers.get('link')

failing when they randomly give you a Link (capital L) instead of a link (lower case l) :confused:

Have not run into this yet but will keep a look out :sweat_smile: