Shopify store catalogs
Read any public Shopify store: products, variants and stock, collections, search, reviews, pages, blogs and the contacts each store publishes.
Overview
Pass any public Shopify store, as a domain or an https URL, and read its published catalog: products with every variant price and stock flag, collections, search, reviews, pages, blogs and the contacts the store publishes. Nothing here adds to a cart, checks out or calls an admin API.
| What | Endpoints | Credits |
|---|---|---|
Is it Shopify? | 1 | |
Store identity | 3 | |
Profile and published contacts | 14 | |
A page of products (catalog, on sale, new arrivals, best sellers, a collection) | POST /v1/retail/shopify/products and four more | 3 for 50 or fewer, 9 above |
One product, its stock, related products | 2 | |
Up to 50 products by handle | 2 per product found | |
Search and suggestions | 2 | |
Collections | 4 | |
Product reviews | 9 + 2 per further page | |
Pages, blogs, articles | POST /v1/retail/shopify/pages, POST /v1/retail/shopify/blogs and three more | 3 |
Sitemap | 9 | |
Catalog stats | 9 per page scanned |
Every catalog route takes store, an optional locale (the path prefix a store uses for another market, such as en-ca) and an optional market, which is echoed on the answer and does not change the currency. The currency is the store's own.
Check and identify a store
POST /v1/retail/shopify/store/check says whether an address publishes a Shopify catalog, and answers 200 with password_protected: true for a store behind its password page. Every other route answers 422 for an address that is not a public Shopify catalog or a password-protected store, and does not charge for it.
curl -X POST "https://api.scrapercompany.com/v1/retail/shopify/store/check" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"store":"allbirds.com"}'{
"store": "allbirds.com",
"is_shopify": true,
"reachable": true,
"catalog_public": true,
"password_protected": false
}POST /v1/retail/shopify/store returns the name, domain, currency, country, ships-to countries and the published product and collection counts. POST /v1/retail/shopify/store/profile adds the theme, storefront apps, policy links and menus, and contacts: the business emails, phones and socials the store publishes on its homepage or contact page (each list is present and empty when there are none). Phones come back with a leading +. A person named in the store's structured data, a founder for example, is not returned.
Products and collections
POST /v1/retail/shopify/products reads one page of the public catalog. The same page, filtered or sorted, is POST /v1/retail/shopify/products/on-sale (compare-at price above the current price), POST /v1/retail/shopify/products/new-arrivals (newest first) and POST /v1/retail/shopify/products/best-sellers (the store's best-selling order); POST /v1/retail/shopify/collections/products reads one collection. Each takes limit (1-250, default 50), and page or the cursor from the previous page's next_cursor.
curl -X POST "https://api.scrapercompany.com/v1/retail/shopify/products" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"store":"allbirds.com","limit":50}'{
"store": "allbirds.com",
"currency": "USD",
"products": [
{
"title": "Women's Allbirds Flip Flop - Dusty Pink",
"handle": "womens-allbirds-flip-flop-dusty-pink",
"vendor": "Allbirds",
"available": false,
"low_stock": false,
"price": {
"min": {
"amount": "25.00",
"amount_minor": 2500,
"currency": "USD"
},
"max": {
"amount": "25.00",
"amount_minor": 2500,
"currency": "USD"
}
},
"compare_at_price": {
"min": {
"amount": "50.00",
"amount_minor": 5000,
"currency": "USD"
},
"max": {
"amount": "50.00",
"amount_minor": 5000,
"currency": "USD"
}
},
"on_sale": true,
"discount_percent": 50,
"variants": [
{
"id": 42146889039952,
"title": "5",
"sku": "A12513W050",
"available": false,
"price": {
"amount": "25.00",
"amount_minor": 2500,
"currency": "USD"
},
"quantity": 0,
"low_stock": false
}
]
}
],
"next_cursor": "…"
}- Prices are
{amount, amount_minor, currency}:amountis a decimal string andamount_minoran integer. A compare-at of 0 means the store published none. - A list page keeps at most 100 variants and 25 images per product;
variants_omittedandimages_omittedcount what was left off. The price span,availableandlow_stockstill use every variant. quantityis a number only when the store publishes a stock count; otherwise it is null andlow_stockis false.low_stockis true for a published count of 1 to 5.- Past 25,000 products (
page × limit) the walk continues through the store's collection feeds, so the same product can appear twice.
POST /v1/retail/shopify/collections lists up to 50 published collections a page; when a page is full, next_page is the next page number.
One product, a batch, stock and related products
POST /v1/retail/shopify/products/detail takes a handle or a product URL on the store and returns every variant and image, with barcodes and selling plans when the store publishes them. POST /v1/retail/shopify/products/batch takes up to 50 handles and charges 2 credits per product found: a missing handle is a not_found row, one that could not be read an unavailable row, and neither is billed. A repeated handle is read once.
curl -X POST "https://api.scrapercompany.com/v1/retail/shopify/products/detail" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"store":"kith.com","handle":"tb0a2pdqamx1"}'POST /v1/retail/shopify/products/inventory returns each variant's availability and published count, and POST /v1/retail/shopify/products/recommendations the store's own related products for one handle. Repeated detail and inventory lookups of the same product are served from a 15-minute cache. An unknown handle is a free 404.
Search and suggestions
POST /v1/retail/shopify/products/search (q, mode full or suggest) and POST /v1/retail/shopify/search/suggestions both read the store's suggest feed and cost 2 credits; an empty result is free.
Product reviews
POST /v1/retail/shopify/products/reviews takes product (a handle or product URL), max_reviews (default 50, at most 500), min_rating, max_rating and cursor. It reads the Judge.me widget or the store's own product-review markup from the product page, or schema.org Review markup when neither is there; any other review widget is a free 422. Each review has a stable review_id, rating, title, body, an ISO date, verified_buyer, photo and video URLs, helpful_votes when present and source (judgeme, spr or jsonld). Reviewer names are not returned, and an email address in the body is removed.
curl -X POST "https://api.scrapercompany.com/v1/retail/shopify/products/reviews" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"store":"allbirds.com","product":"womens-wool-runner","max_reviews":20}'{
"store": "allbirds.com",
"product": "womens-wool-runner",
"source": "judgeme",
"summary": {
"average": 4.5,
"reported_total": 40,
"scraped_count": 1,
"distribution": {}
},
"reviews": [
{
"review_id": "101",
"rating": 5,
"title": "Loved them",
"body": "Wore them all week.",
"date": "2024-05-01",
"verified_buyer": true,
"photos": [
"https://cdn.example/rev/101.jpg"
],
"videos": [],
"helpful_votes": 3,
"source": "judgeme"
}
]
}The product page is the first page and costs 9 credits; each further Judge.me page of 20 reviews costs 2. A later page is read only while the credits held for max_reviews cover it (the default of 50 holds 13); the answer then carries next_cursor. No widget and no reviews is an empty list and is free.
Pages, blogs, sitemap and catalog stats
- POST /v1/retail/shopify/pages and POST /v1/retail/shopify/pages/detail: the store's published pages (about, size guide and the like).
- POST /v1/retail/shopify/blogs lists the blogs named in the sitemap; POST /v1/retail/shopify/blogs/articles and POST /v1/retail/shopify/blogs/article read articles from the blog's Atom feed, with the store's own byline. Commenters' names are not returned.
- POST /v1/retail/shopify/store/sitemap returns the locations in the sitemap index, in one document.
- POST /v1/retail/shopify/store/catalog-stats scans up to
max_pagescatalog pages of 250 (1-5, default 1) and returnsproducts_seen,vendorsand the price span in minor units, at 9 credits per page scanned.
Pages, blogs and articles cost 3 credits; an empty list and an unknown handle are free.
Errors and what is free
| Result | Status | Charged |
|---|---|---|
Not a public Shopify catalog, password-protected store, catalog not public | 422 (store/check answers 200) | No |
Unsupported reviews widget, invalid cursor, bad input | 422 | No |
Unknown product, collection, page, blog or article | 404 | No |
The store did not answer, or blocked the request | 503 with Retry-After: 15 | No |
Empty page, list, search or scan | 200 | No |
Every endpoint's fields, examples and errors are under API reference → Shopify. Other retail sources (Amazon, Walmart) are in Beyond travel.
Questions about this page?
Send the page link and your question, and the team will answer.