Shopify Products Scraper & eBay Search Scraper
Pricing
from $5.00 / 1,000 product scrapeds
Shopify Products Scraper & eBay Search Scraper
Scrape Shopify stores (public products.json) and eBay search results into one clean schema: one row per variant with price, compare-at price, currency, SKU, stock, images and URL. Blocked or empty targets are reported with a reason and never billed.
Pricing
from $5.00 / 1,000 product scrapeds
Rating
0.0
(0)
Developer
Turgay NANTA
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
a month ago
Last modified
Categories
Share
Shopify Scraper & eBay Scraper: Products, Variants and Prices in One Clean Schema
Copying products from competitor stores into a spreadsheet by hand is slow, and most scrapers either break on odd price formats or return an empty file without telling you why.
Give the Actor one or more Shopify store addresses, or eBay search terms. It returns a clean product dataset: one row per variant, with title, variant, vendor, product type, tags, SKU, price, compare-at price, currency, an approximate USD price, availability, images and the product URL. Every row has the same fields, whether it came from Shopify or eBay, and when a target returns nothing, the run tells you why.
- Shopify stores: reads the store's public product feed (
/products.json), 250 products per page, every variant as its own row. - eBay search (beta): reads the first results page of each search term: title, price, image and link. eBay currently refuses many automated requests, even through a residential proxy; see Limits.
- One fixed schema: a missing value is
null, never a missing column. - Honest prices: US and EU number formats and currency symbols are parsed; unclear values stay
nullinstead of being guessed. - Never silently empty: blocked, disabled or changed pages are reported with a status and a reason.
- Pay only for records: empty or blocked results are not billed.
What it costs: $0.005 per product row, so 100 rows cost about $0.50. Details in Pricing.
This is a deterministic scraper. There is no AI in it: what you see in the dataset is what was parsed from the source.
At a glance
| Input | Shopify store addresses (storeUrls) or eBay search terms (searchQueries) |
| Output | Product dataset (one row per variant) + RUN_SUMMARY with per-target status and a data health report |
| Shopify fields | Product and variant IDs, title, variant title, handle, vendor, product type, tags, SKU, price, compare-at price, currency, USD price, availability, images, URL |
| eBay fields | Title, price, currency, USD price, image, URL, and condition when the results page shows it |
| Limits | maxItems rows in total (default 1,000), split evenly across targets |
| Statuses | OK, EMPTY_VALID, BLOCKED, ENDPOINT_DISABLED, RATE_LIMITED, STALE_SELECTOR, HTTP_ERROR |
| Pricing | Per product row; see Pricing |
| Runs on | Apify Console, API, schedules, n8n, Make, Zapier, AI agents via MCP |
Quick start
Shopify store
- Keep Platform on Shopify stores.
- Enter one or more store addresses in Shopify store addresses, for example
allbirds.comorhttps://www.allbirds.com. - Set Store currency (for example
USD). Shopify's feed does not include a currency symbol, so this fills thecurrencyandprice_usdcolumns. - Set Maximum number of records. For a first test, 50-100 is enough.
- Click Start and open the Dataset tab.
eBay search
- Set Platform to eBay search.
- Enter search terms in eBay search terms, for example
mechanical keyboard. - Keep Use a residential proxy on, then click Start.
- If the status is BLOCKED, eBay refused the request even after three attempts from different proxy addresses. Only the $0.0001 start fee is charged; try again later. For dependable results, use Shopify stores.
What the output looks like
| source | title | variant_title | price | currency | price_usd | available | url |
|---|---|---|---|---|---|---|---|
| shopify | Wool Runner | 9 / Natural Black | 98.00 | USD | 98.00 | true | https://store.example/products/wool-runner |
| shopify | Wool Runner | 10 / Natural Black | 98.00 | USD | 98.00 | false | https://store.example/products/wool-runner |
| ebay | Mechanical Keyboard 87 Keys Hot Swap | null | 45.99 | USD | 45.99 | null | https://www.ebay.com/itm/... |
Illustrative rows; your run returns what the store or search page actually lists.
Why use it
Many product scrapers work on the happy path and fail quietly on everything else. This Actor is built around four promises:
- The schema never changes. All rows carry the same 21 fields. A value the source does not provide is
null, so your spreadsheet, database or script never meets a missing column. - One row per variant. Sizes and colors each get their own row with their own price, SKU and availability, which is what price comparison and catalog work need.
- Prices are parsed, not guessed.
$1,299.00,1.299,00 €,1299 ₺and bare numbers become a decimal amount and an ISO currency code. When a value is ambiguous, the amount staysnull. - Empty results come with a reason. If a store disabled its product feed, eBay showed a bot check, or the page layout changed, the run says so with a status and a short explanation instead of returning an empty file.
Typical scraper vs. this Actor
| Typical product scraper | This Actor | |
|---|---|---|
| Same columns for every row | Varies | Always; missing = null |
| Variants | Varies | Every variant as a row |
| EU price formats | Varies | Parsed; unclear stays null |
| Empty result | Often just an empty file | Status + reason per target |
| Billing on empty or blocked pages | Varies | Not billed |
What you get
Dataset: one row per product variant
| Field | Shopify | eBay |
|---|---|---|
source | shopify | ebay |
product_id / variant_id | Shopify IDs | null |
title / variant_title | Product and variant title | Listing title / null |
handle | Product handle | null |
vendor / product_type | From the store | null |
tags | List of tags | null |
sku | Variant SKU | null |
price / compare_at_price | Variant price and compare-at price | Listed price / null |
currency | From Store currency | From the price symbol |
price_usd | Approximate USD value | Approximate USD value |
available | true / false | null |
image / images | First image / all images | Listing image |
url | Product page | Listing link |
condition | null | Condition text when the results card shows it, otherwise null |
seller / shipping | null | null in search mode |
How prices are parsed
| Source value | price | currency |
|---|---|---|
"98.00" with Store currency USD | 98.00 | USD |
"$1,299.00" | 1299.00 | USD |
"1.299,00 €" | 1299.00 | EUR |
"1299 ₺" | 1299 | TRY |
"98.00" without Store currency | 98.00 | null |
| Text with no number | null | null |
Key-value store: RUN_SUMMARY
Written when the run returns records:
total: number of rows in the dataset.statuses: for each store or search term, thestatus, whether a retry is advised, and thereason.data_health: for title, price, currency, availability, image, SKU and URL, how many rows have a value and the ratio;missing_warningslists title, price or URL gaps.
Example:
{"total": 312,"statuses": [{"target": "allbirds.com", "status": "OK", "retry_advised": false, "reason": "250 record(s) parsed."}],"data_health": {"total_records": 312,"field_coverage": {"sku": {"filled": 298, "ratio": 0.96}, "price": {"filled": 312, "ratio": 1.0}},"missing_warnings": []}}
Shortened example; the real block lists every checked field.
When nothing is returned, the dataset holds a single _summary row with the statuses and a note, and no record is billed.
Who it is for
- Dropshippers and e-commerce founders researching what a competitor sells and at what price.
- Pricing analysts comparing prices and discounts (compare-at price) across stores.
- Shopify agencies and developers auditing or migrating a client's catalog.
- Market researchers mapping vendors, product types and tags in a niche.
- eBay resellers checking what is listed for a search term and at which prices.
- Data teams feeding product data into a database or BI tool with a stable schema.
Use cases
Competitor catalog research
Run the Actor on the three to five stores you compete with. Filter by product_type and tags to see how they structure their range, and sort by price to find their entry and premium products.
Price and discount tracking
Schedule the same input daily or weekly and store each run's dataset. Comparing price and compare_at_price between runs shows new discounts and price changes. The Actor gives you clean snapshots; the comparison happens in your sheet or database.
Stock and variant availability
available is reported per variant, so you can see which sizes or colors are sold out in a competitor's store.
Catalog audits for agencies
Pull a client's catalog and check the data_health block: missing SKUs, images or prices show up as coverage below 100%.
eBay market snapshot
Search a product term and see the titles and prices on the first results page. Useful for a quick price range before buying stock or listing an item.
Brand and wholesale research
Before approaching a brand as a retailer or wholesaler, pull its direct-to-consumer store. The vendor, product type, tag and price columns show the full range, the price points and which lines are discounted, so you arrive at the conversation prepared.
Product data for your own tools
Because every row has the same fields, the dataset loads directly into Google Sheets, Airtable, a SQL table or a script without cleanup.
Worked example: pricing a new product line
A small shoe brand plans a new wool sneaker and wants to know how competitors price similar products.
- Run on four competitor stores with Store currency set to
USDand Maximum number of records at 800 (200 per store). - Filter rows by
product_typeortagsfor sneakers. - Check the price range: the lowest and highest
price, and which variants have acompare_at_price(a discount). - Check availability: sizes marked
available: falseacross several stores hint at high demand. - Schedule a weekly run and keep each week's export to follow discounts and restocks.
How it works
- Proxy. When Use a residential proxy is on, an Apify residential proxy is used. If a proxy cannot be set up, the run continues without one and logs a warning.
- Shopify. For each store, the Actor requests
/products.json250 products at a time and moves to the next page until the catalog ends or the store's share ofmaxItemsis reached. - eBay. For each search term, the Actor loads the first eBay search results page and reads the listing cards. Placeholder cards such as "Shop on eBay" are dropped.
- Normalize. Every product and variant is mapped to the same 21 fields; prices are parsed into amount and currency.
- Check. Each request gets a status: OK, or a named reason why nothing came back.
- Deduplicate. The same product variant is kept only once.
- Deliver. Rows go to the dataset and each row is billed as it is written;
RUN_SUMMARYholds statuses and data health.
Input
| Field | Description |
|---|---|
platform | shopify (default) or ebay |
storeUrls | Shopify store addresses, with or without https:// |
searchQueries | eBay search terms |
maxItems | Maximum rows in total, one row per variant. Default 1,000. Split evenly across stores or search terms. |
storeCurrency | Shopify store currency, for example USD, EUR, GBP, TRY. Recommended; see Tips. |
useResidentialProxy | Use an Apify residential proxy. Default on. |
Example: two Shopify stores
{"platform": "shopify","storeUrls": ["allbirds.com", "https://www.example-store.com"],"storeCurrency": "USD","maxItems": 400}
Example: eBay search
{"platform": "ebay","searchQueries": ["mechanical keyboard", "wireless mouse"],"useResidentialProxy": true}
Pricing
This Actor charges per event. Current prices are on the Pricing tab; at the time of writing:
| Event | When | Price |
|---|---|---|
actor-start | Once per run | $0.0001 |
item-scraped | Per product row written to the dataset | $0.005 |
| Rows in one run | Total (approx.) |
|---|---|
| 100 | $0.50 |
| 500 | $2.50 |
| 1,000 (the default maximum) | $5.00 |
| 5,000 | $25.00 |
A row is one variant, so a store with 200 products and 4 variants each can produce 800 rows. Set Maximum number of records to cap the cost of a run. When a target is blocked or returns nothing, no record is billed.
Integrations
API
curl -X POST "https://api.apify.com/v2/acts/enezli~shopify-ebay-product-research/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"platform":"shopify","storeUrls":["allbirds.com"],"storeCurrency":"USD","maxItems":100}'
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("enezli/shopify-ebay-product-research").call(run_input={"platform": "shopify", "storeUrls": ["allbirds.com"],"storeCurrency": "USD", "maxItems": 100})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["title"], row["variant_title"], row["price"], row["available"])
Schedules
Save the input as a task and add a daily or weekly schedule to build a price and stock history.
n8n, Make, Zapier
Run Actor, then read the dataset items and append them to Google Sheets, Airtable or a database. Read RUN_SUMMARY to alert when a store's status is not OK.
AI agents (MCP)
Available through the Apify MCP server, so an assistant can pull a store's catalog on request and answer questions about its prices and ranges.
Workflow recipes
Weekly competitor price sheet. One task with your competitors' stores and Store currency set, scheduled every Monday. An n8n or Make flow appends the rows to a Google Sheet with the run date, so a pivot table shows each variant's price over time.
Sold-out alert. Run daily on one store and keep only rows where available is false. Send the list of sold-out variants to Slack; restocks show up as rows that switch back to true.
Discount watch. Filter rows where compare_at_price is higher than price. The difference is the advertised discount; tracking it weekly shows when a competitor starts a sale.
Catalog migration check. Before and after moving a store to a new theme or app, pull the catalog and compare row counts and data_health. Missing images or SKUs show up at once.
Tips for better results
- Always set Store currency for Shopify. The Shopify feed gives prices without a currency symbol. Without this field,
currencyandprice_usdstaynull. - Start small. Use
maxItems50-100 to check the output before pulling a whole catalog. - Remember variants count as rows. Stores with many sizes and colors fill
maxItemsquickly. - Keep the residential proxy on for eBay. eBay blocks many datacenter addresses.
- Treat
price_usdas an estimate. It uses fixed built-in rates for USD, EUR, GBP, TRY, JPY, CAD and AUD, not live exchange rates. Other currencies get no USD value. - Use exact store addresses. A store's own domain works best; redirects are followed automatically.
- Check
RUN_SUMMARYafter each run to see which targets returned OK and how complete the key fields are.
Limits
- Shopify stores that disabled their public product feed cannot be read; the status says ENDPOINT_DISABLED.
- eBay mode is in beta. In our September 2026 test runs, eBay refused the search page (HTTP 403) even through a residential proxy. The Actor retries up to three times with a new proxy address, then reports BLOCKED and bills nothing but the start fee.
- eBay mode reads only the first results page of each search term, and only the fields shown on the results page. Seller, shipping, item ID and SKU are not collected.
- eBay changes its page layout from time to time. When the page loads but no listing can be read, the status is STALE_SELECTOR and nothing is billed.
- For eBay price ranges such as "$20.00 to $35.00", the lower price is kept.
- The Actor does not compare runs. Price change tracking means storing snapshots and comparing them yourself.
- Only public product data is read. Password-protected stores are not supported.
Troubleshooting
| Status or symptom | Meaning | What to do |
|---|---|---|
ENDPOINT_DISABLED | The store returned 404 for its product feed | The store disabled the feed; it cannot be read with this Actor |
BLOCKED | Access denied, or a bot check was detected | Turn on the residential proxy. If it is already on, the reason says so: the site is refusing automated access, try again later |
RATE_LIMITED | Too many requests (HTTP 429) | Wait and retry; spread large jobs over several runs |
STALE_SELECTOR | The page loaded but no product could be read | For eBay, the layout may have changed; for a store URL, check that it is a Shopify store |
EMPTY_VALID | A valid but empty response | The store or search has no products |
HTTP_ERROR | Server error or unexpected status | Retry later |
currency is null | Store currency was not set | Set Store currency |
Fewer rows than maxItems | The catalog or search page has fewer products, or the limit was split across targets | Normal; check RUN_SUMMARY |
| "'storeUrls' is empty" | Shopify was selected without a store | Add at least one store address |
FAQ
Does it work with any Shopify store?
With stores that keep the public /products.json feed enabled, which is the default for Shopify stores. If a store disabled it, you get the ENDPOINT_DISABLED status and no charge for records.
Why one row per variant? Because price, SKU and availability belong to the variant. One row per variant keeps each price correct and makes filtering by size or color easy.
Can I scrape several stores in one run?
Yes. Add several addresses; maxItems is split evenly between them and the rows are combined in one dataset.
Do I need a Shopify account or API key? No. The Actor reads the public product feed that Shopify stores publish for visitors. No login, app install or store permission is needed.
Which eBay site is searched? eBay.com. Prices are read as shown on that site, usually in US dollars.
What data does it collect? Only public product information: titles, variants, prices, availability, images, tags and links. No customer or order data is read, and nothing behind a login is accessed.
Is there AI in this Actor? No. It parses the data the source provides. No values are generated.
How accurate is price_usd?
It uses fixed conversion rates built into the Actor, so treat it as an approximate comparison value. The original price and currency are always kept.
Does it track price changes? It produces a clean snapshot each run. Schedule it and compare the snapshots in your sheet or database.
Am I charged when a store is blocked? Only the start fee ($0.0001). Records are billed only when they are written to the dataset.
What happens to duplicate products? The same product variant (same source, product ID and variant ID) is kept once. Rows without IDs, such as eBay results, are de-duplicated by link and title.
Can I use the output in a spreadsheet? Yes. Export the dataset as CSV or Excel from the Storage tab, or read it through the API. The columns are the same in every run.
Can I get more than the first eBay results page? Not in this version. Use several specific search terms to cover more listings.
Trademarks
This Actor is not affiliated with, endorsed by, or connected to Shopify or eBay. All product names are trademarks of their respective owners.