How it will work: 3 steps
- Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
https://www.allbirds.comin Shopify store URLs. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
Export public products from any Shopify store to JSON, CSV or Excel. You get one row per product with prices, sale prices, stock, variants, SKUs, images, tags and dates. Add one store URL, such as https://www.allbirds.com, and click Start. There is no login and no API key.
Good for
- Watch a competitor's prices, sales and stock.
- Copy a supplier's catalog with SKUs and images into your own system.
- Get a daily list of only the new products in a store.
Not a good fit
- Stores that are not on Shopify, or that switched the public feed off. You get a status row, not products.
- Inventory numbers. Shopify's public feed only says if a variant is in stock (
available). It does not give quantities. - Private data: orders, customers, costs, admin-only fields and unpublished products.
- More than 25,000 products from one feed. This is a Shopify limit. Use collections for bigger catalogs.
Who uses it
Online sellers
Watch a competitor's prices, sales and stock.
Dropshippers
Copy a supplier catalog with SKUs and images into your system.
Marketing agencies
Watch prices for many brands on a schedule.
Price
Prices will be shown after release.
Questions
Do I need a Shopify login or API key?
No. It reads the public product feed. Password-protected stores are skipped.
Is the stock number exact?
No. The public feed only says if a variant is in stock. Quantities are not public.
Why are there no products in an only-new run?
Nothing new was published since the last run with the same stateKey.
What if the store is not on Shopify?
You get a status row, not products.
How fresh is the data?
Each row is read live from the store at fetchedAt.
Details
Step by step on Apify
- Open the Input tab.
- In Store URLs (
storeUrls), add a store, for examplehttps://www.allbirds.com. - Keep the prefilled Max products per store (
maxProducts) of 20 for a first test. The default for runs without this field is 1,000. - Click Start.
- Open the Products view in the Output tab. Check
title,priceandavailable. Rows withrecordType: productare products.
Use cases
| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Competitor price and sale watch | storeUrls, schedule | Product row | price, compareAtPrice, onSale, available | Dataset export or API to a sheet |
| Supplier catalog import | storeUrls, includeVariants: true | Product row with variants | variants[].sku, variants[].price, images, description | JSON/CSV import into your store or PIM |
| New product alerts | storeUrls, onlyNew: true, schedule | New product rows | title, url, publishedAt, isNew | Webhook or integration on run finish |
| Collection research | Collection URL or collection | Product row | productType, vendor, tags, price | Dataset export |
Tips for better results
- Use only-new mode on a daily schedule to get new products only.
- Pick one collection when you need only part of a big store.
- Use collections for stores with more than 25,000 products.
Limits and good to know
- 25,000 products per feed. Shopify does not serve more from one feed. For bigger stores, run collections one by one
- Time. A big store gives about 120 products per second: 1,000 products took about 5 seconds, 18,847 products took 154 seconds. One store up to the 25,000 limit fits in the default 300-second timeout. For several big stores in one run, raise the timeout in Run options or split the stores
- Currency. Prices are in the store's base currency (
currency), whatever country the run comes from. If the store answers in another market's prices,currencyisnulland the run summary has a warning - No proxy needed. The feed is public. The Actor waits when a store asks it to slow down (HTTP 429 or 503)
- Order. Rows come newest first by publish date, as the store's feed gives them
- Partial results. If a store fails after some pages, the rows already saved stay in the Dataset. The store also gets a status row with
status: errorandproductsFound. The run summary lists every store with its result
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"recordType": "product",
"status": "complete",
"store": "www.allbirds.com",
"storeName": "Allbirds",
"collection": null,
"productId": 7340901859408,
"handle": "womens-allbirds-flip-flop-dusty-pink",
"title": "Women's Allbirds Flip Flop - Dusty Pink",
"vendor": "Allbirds",
"productType": "Shoes",
"price": 25,
"priceMax": 25,
"compareAtPrice": 50,
"onSale": true,
"currency": "USD",
"available": true,
"variantsCount": 7,
"availableVariantsCount": 1,
"options": [{ "name": "Size", "values": ["5", "6", "7", "8", "9", "10", "11"] }],
"variants": [
{
"variantId": 42146889039952,
"title": "5",
"sku": "A12513W050",
"price": 25,
"compareAtPrice": 50,
"available": false,
"option1": "5",
"option2": null,
"option3": null,
"grams": 455,
"requiresShipping": true,
"imageUrl": null,
"position": 1
}
],
"url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
"createdAt": "2026-03-27T21:03:50.000Z",
"updatedAt": "2026-10-17T08:09:02.000Z",
"publishedAt": "2026-09-25T23:58:13.000Z",
"isNew": null,
"source": "shopify-products-json",
"fetchedAt": "2026-10-17T08:12:27.141Z"
}Data fields (37)
| Field | Type | Meaning |
|---|---|---|
recordType | string | Row type: product, or store-status for a store that was not found, failed or stopped early. |
status | string | complete for product rows; not_found (no Shopify feed, collection missing, password-protected, empty) or error (blocked, rate limited, unavailable, stopped) for store-status rows. |
store | string | Store domain the data came from, e.g. www.allbirds.com. |
storeName | string | Store name from the store's public meta.json, when available. |
storeUrl | string | Store homepage URL. |
collection | string | Collection handle when the export was limited to a collection; null for the whole catalog. |
productId | integer | Shopify product ID. |
handle | string | Product handle (URL slug). |
title | string | Product title. |
vendor | string | Brand or vendor. |
productType | string | Product type set by the store. |
tags | array | Product tags. |
description | string | Product description as plain text (HTML removed, up to 5,000 characters). |
price | number | Lowest variant price in the store currency. null if the store hides it; never 0 for a missing price. |
priceMax | number | Highest variant price. |
compareAtPrice | number | Compare-at (original) price of the cheapest variant; null when there is none. |
onSale | boolean | true when compareAtPrice is above price. |
currency | string | Store currency code from meta.json, e.g. USD; null when the store does not publish it. |
available | boolean | true if at least one variant is in stock. |
variantsCount | integer | Number of variants. |
availableVariantsCount | integer | Number of variants in stock. |
options | array | Product options with their values, e.g. Size: 8, 9, 10. |
variants | array | Variants with variantId, title, sku, price, compareAtPrice, available, option1-3, grams, requiresShipping, imageUrl and position; null when Include variants is off. |
imageUrl | string | Main product image URL. |
images | array | All product image URLs. |
createdAt | string | When the product was created (UTC ISO 8601). |
updatedAt | string | When the product was last updated (UTC ISO 8601). |
publishedAt | string | When the product was published (UTC ISO 8601). |
url | string | Product page URL. |
isNew | boolean | Only new products mode: true for a product not seen in earlier runs; null on the first run and when the mode is off. |
statusCode | string | Store-status rows: NOT_SHOPIFY, COLLECTION_NOT_FOUND, PASSWORD_PROTECTED, NO_PRODUCTS, BLOCKED, RATE_LIMITED, SOURCE_UNAVAILABLE, CHARGE_LIMIT, INVALID_URL and others. |
statusMessage | string | Store-status rows: plain-English reason. |
input | string | Store-status rows: your input value as given. |
productsFound | integer | Store-status rows: product rows saved for this store before the stop. |
source | string | Data source: shopify-products-json (the store's public storefront feed). |
sourceUrl | string | Feed page URL the row came from. |
fetchedAt | string | When the row was fetched (UTC ISO 8601). |
Input settings (6)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| Shopify store URLs required | storeUrls | array | ["https://www.allbirds.com"] |
| Collection (optional) | collection | string | |
| Max products per store | maxProducts | integer | 20 |
| Only new products | onlyNew | boolean | false |
| Include variants | includeVariants | boolean | true |
| State key (only new products) | stateKey | string |


