# 🛍️ Shopify Store Leads Scraper - Emails, Phones & Ratings (`scraper-engine/shopify-store-leads-scraper`) Actor

Spotify Play Count Scraper extracts public track data including play counts, song titles, artists, albums, release dates, durations, and Spotify URLs. Monitor streaming performance, compare tracks, analyze music trends, and build structured datasets for research.

- **URL**: https://apify.com/scraper-engine/shopify-store-leads-scraper.md
- **Developed by:** [Scraper Engine](https://apify.com/scraper-engine) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Shopify Store Leads Scraper - Emails, Phones & Ratings

Shopify Store Leads Scraper - Emails, Phones & Ratings finds real, currently-operating Shopify stores by product keyword or category and returns structured lead data — emails, phone numbers, business addresses, review ratings, and sample products — as clean JSON, no HTML parsing needed. Every store streams into the dataset the moment it's enriched, split into ready-to-browse views for contacts, ratings, and products. Add a keyword below and start a run to see leads arrive in real time.

### 🔍 What is Shopify Store Leads Scraper - Emails, Phones & Ratings?

Shopify Store Leads Scraper - Emails, Phones & Ratings is an Apify Actor that queries shop.app — Shopify's own consumer shopping app — to discover real Shopify-powered stores by product keyword and/or category, then enriches each unique store with its published contact channels, business address, review analytics, and sample products. It returns structured JSON with **no Shopify account, shop.app login, or API key required** — the Actor mints its own guest session internally. It's built for growth/sales teams doing Shopify lead generation, dropship and wholesale sourcing, and market-research or AI/RAG pipelines that need a verified list of real Shopify merchants.

### 📖 What Shopify store data is publicly available to scrape?

Every field this Actor returns is data a merchant chose to publish on shop.app — the same public storefront data any shopper sees while browsing or searching the app, no login required.

| Data Category | Published by the merchant on Shop.app | Not exposed by Shop.app |
| --- | --- | --- |
| Store name, website & myshopify.com domain | Always public | — |
| Business address (street, city, region, postal code, country) | Public only if the merchant added one | Blank when not published |
| Contact channels (email, phone, web, social links) | Public only if the merchant listed them | Blank when not published |
| Product review analytics (average rating, ratings count, reviews count) | Public | — |
| Sample product listings (title, price, currency, image) | Public — up to 3 per store | Full catalog, exact stock levels |
| Order history, customer records, sales/financial data | Never published on shop.app | Shopify admin login (store owner only) |

Shopify Store Leads Scraper - Emails, Phones & Ratings only returns publicly visible data — what any visitor to shop.app sees. Nothing behind a login wall.

### 📊 What data can I extract with Shopify Store Leads Scraper - Emails, Phones & Ratings?

The Actor returns one record per discovered Shopify store, covering its identity, published contacts and address, review analytics, and up to three sample products.

| Field Name | Description |
| --- | --- |
| `id` | Shop.app's internal store identifier (opaque numeric string). |
| `name` | The store's display name. |
| `websiteUrl` | The store's live storefront URL (`utm_source=shop_app` kept; per-run session-tracking parameters stripped). |
| `myshopifyDomain` | The store's underlying `*.myshopify.com` domain. |
| `shareUrl` | The store's public shop.app share link. |
| `address` | Business address object — `null` when the merchant hasn't published one (see breakdown below). |
| `contacts` | Array of every public contact channel the store lists — `{ method, target }` pairs. |
| `rating` | Average product rating across the store's catalog. |
| `totalProductRatings` | Total number of product ratings behind that average. |
| `totalProductReviews` | Total number of written product reviews. |
| `sampleProducts` | Up to 3 real products sold by the store (see breakdown below). |
| `scrapedAt` | ISO-8601 UTC timestamp of when this store record was collected. |
| `searchQuery` | Which input search query surfaced this store — `null` when discovered by category alone. |

#### 🏬 Store identity fields

`id`, `name`, `websiteUrl`, `myshopifyDomain`, `shareUrl`, `searchQuery`, `scrapedAt` — what the store is called, where it lives online, and which input run found it.

#### 📇 Contact & address fields

- **`contacts[]`** — `method` (e.g. `email`, `phone`, `web`, `facebook`, `instagram` — whatever channels the store itself publishes) and `target` (the email address, phone number, or URL).
- **`address`** — `address1`, `address2`, `city`, `zone`, `zoneCode`, `country`, `postalCode`, `company`, `phone`, and `formatted` (an array of pre-formatted display lines).

#### ⭐ Ratings & sample products

- **`rating`**, **`totalProductRatings`**, **`totalProductReviews`** — review analytics for the store as a whole.
- **`sampleProducts[]`** — `title`, `price`, `currency`, `url`, `imageUrl` for up to 3 real products.

### 🤔 Why not build this yourself?

Shop.app has no public developer API, and Shopify's own Admin and Storefront APIs are scoped to a single authenticated store — neither one lets you search across the platform's stores by keyword or category. Building this yourself means reverse-engineering shop.app's internal GraphQL schema, keeping pace with its Remix-based asset bundling (endpoint paths have to be resolved live from hashed JS chunk names, since they're never literal strings in the bundle), and clearing its guest-session gate, which rejects plain HTTP clients **and** headless browsers alike — only a real, visible Chrome session passes it. On top of that, you'd own proxy rotation and cost yourself. This Actor already handles all of it: live endpoint discovery every run, a real (Xvfb-backed) Chrome session for the one-time guest sign-in, and an automatic Direct → Datacenter → Residential proxy ladder that only spends a proxy tier when shop.app actually blocks a request.

### 🚀 How to use Shopify Store Leads Scraper - Emails, Phones & Ratings

This Actor runs on the Apify platform — there's no separate signup or API key to obtain beyond an Apify account.

1. Open the Actor's page in the Apify Store and click **Try for free** (or **Start**, if you already have it).
2. Add at least one keyword to **🔎 Search Queries (bulk)**, or pick a **📂 Category** — the Actor needs one of the two to run; leaving both empty stops the run with a clear error.
3. Optionally narrow results with **📍 Store Location**, the **🎛️ Product Filters** (price, on-sale, in-stock, ships-from/to), and **⏭️ Skip Stores From Previous Runs**.
4. Click **▶️ Start**.
5. Open the **Output** tab — while the run is still going or after it finishes — and export the results as JSON or CSV, or switch between the Overview, Contacts & Address, Ratings & Reviews, and Sample Products views.

#### 📦 How to scale to bulk store-lead extraction

`searchQueries` is a bulk field (`stringList` editor) — add as many keywords as you like and each is scraped as its own independent search, with every store streaming into the same dataset as it's found. `📦 Max Stores (per query)` (`maxItems`) applies per keyword, so the run's ceiling is roughly `maxItems × number of queries`. There's no need to start separate runs for each keyword — one run with a long `searchQueries` list covers all of them.

### 🎯 What can you do with Shopify store data?

- 📈 A growth marketer building a cold-outreach list uses `contacts` (the `email`/`phone` entries) and `name` to compile a verified list of Shopify merchants in one niche, without hand-collecting them from shop.app.
- 🤝 A wholesale/dropship sourcing manager combines `category` with `sampleProducts[].price` to shortlist Shopify stores selling in a niche at a target price point before reaching out.
- 🌍 A regional sales rep uses `address.country` and the `shipsTo` filter to narrow leads down to stores based in, or shipping to, a specific target market.
- 🧪 A market researcher compares `rating`, `totalProductRatings`, and `totalProductReviews` across competing stores in the same `category` to gauge review strength before entering a niche.
- 🤖 An AI agent or RAG pipeline ingests the JSON output directly — `name`, `address.formatted`, and `contacts` feed a lead-enrichment agent that drafts a personalized outreach message per store, with no HTML parsing or selectors involved.

Because the output is typed, normalized JSON, any of these records can be handed straight to an agent framework or MCP client as tool output — see Integrations below.

### 🛡️ How does Shopify Store Leads Scraper - Emails, Phones & Ratings handle rate limits and blocking?

By default every request goes straight to shop.app with no proxy, which is enough for most runs. If shop.app starts rejecting requests, the Actor escalates itself automatically: Direct → 🖥️ Datacenter proxy → 🏠 Residential proxy, retrying the residential tier up to 3 times on a fresh IP before giving up on that one request; once residential is reached, the run stays on it for every remaining request (including the one-time Chrome session mint), and every switch is logged. Independently, `🔁 Max Retries Per Request` (`maxRetries`, default 3) controls how many times one request is retried on its *current* proxy tier, with a growing delay, before the Actor escalates to the next tier. The one-time guest session is minted with a real, visible Chrome session running under a virtual display, since shop.app's guest sign-in endpoint rejects both plain HTTP clients and headless browsers. If a single store's contacts/rating/sample-products fetch fails outright, that one store is skipped with a warning and the run continues; if shop.app becomes completely unreachable for 12 requests in a row, the Actor logs the failure clearly and stops instead of looping forever. The Actor does not solve CAPTCHAs.

⚠️ No proxy ladder can guarantee shop.app won't block a request — the Direct → Datacenter → Residential escalation maximizes the chance of success but isn't a 100% guarantee. If a run keeps coming back with 0 stores, configure a Residential proxy explicitly in `proxyConfiguration` rather than relying on the automatic fallback alone.

### ⬇️ Input

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `searchQueries` | No | array | One or more product keywords to search for — each is scraped as its own independent search and results stream into the same dataset. Leave empty to discover stores by Category alone. | `["wireless headphones", "organic coffee"]` |
| `category` | No | string | Filter to stores selling in this product category; works alone or combined with a search query. Default `""` (no filter) — one of 15 values (blank, or a `gid://shopify/ProductCategory/…` value), see below. | `"gid://shopify/ProductCategory/7"` |
| `storeLocation` | No | string | Find stores based in a specific country or region. Stores with no published business address are still included as likely matches. Default `""` (any location) — see the full list of regions/countries below. | `"US"` |
| `maxItems` | No | integer | Maximum number of unique stores to return per search query. Default `10`, minimum `1`, maximum `100000`. | `50` |
| `skipPreviouslyScraped` | No | boolean | Skip stores already returned in a previous run of the same search (query + category + store location + ships-to combination). Default `false`. | `true` |
| `priceMin` | No | integer | Only discover stores selling products above this price (USD). Minimum `0`. | `20` |
| `priceMax` | No | integer | Only discover stores selling products below this price (USD). Minimum `0`. | `100` |
| `onSale` | No | boolean | Only discover stores with products currently on sale. Default `false`. | `true` |
| `inStock` | No | boolean | Only discover stores with products currently in stock (matches shop.app's own default search behaviour). Default `true`. | `true` |
| `shipsFrom` | No | boolean | Only discover stores that ship FROM the selected Store Location. Has no effect if Store Location is left as "Any location". Default `false`. | `true` |
| `shipsTo` | No | string | Only discover stores that ship TO a specific destination country. Default `""` (any country) — see the full list of country codes below. | `"GB"` |
| `proxyConfiguration` | No | object | Default = no proxy (direct connection). Auto-escalates Direct → Datacenter → Residential if shop.app blocks requests; override to force a specific proxy from the start. Prefill: `{"useApifyProxy": false}`. | `{"useApifyProxy": false}` |
| `maxRetries` | No | integer | How many times to retry one blocked/failed request on the same proxy tier before escalating to the next tier. Default `3`, minimum `1`, maximum `10`. | `3` |
| `maxScanned` | No | integer | Safety cap on how many raw search result rows a single query may scan before giving up, even if `maxItems` hasn't been reached. Default `20000`, minimum `100`, maximum `200000`. | `20000` |

⚠️ `maxItems` defaults to `10` in the Apify Console UI, but the Actor's own code falls back to `50` if the field is omitted entirely (e.g. an API call that doesn't send it at all) rather than left at its schema default — worth knowing if you call the Actor directly through the API without the Console form.

<details><summary>Full enum values for <code>category</code>, <code>storeLocation</code>, and <code>shipsTo</code></summary>

**`category`** — `""` (🚫 No category filter), `gid://shopify/ProductCategory/1` (👗 Women), `gid://shopify/ProductCategory/2` (👔 Men), `gid://shopify/ProductCategory/3` (💍 Accessories), `gid://shopify/ProductCategory/5` (💄 Beauty), `gid://shopify/ProductCategory/6` (🏠 Home), `gid://shopify/ProductCategory/7` (🔌 Electronics), `gid://shopify/ProductCategory/9` (🧳 Luggage & bags), `gid://shopify/ProductCategory/10` (🧸 Toys & games), `gid://shopify/ProductCategory/15` (🐾 Pet supplies), `gid://shopify/ProductCategory/69` (🏋️ Fitness & nutrition), `gid://shopify/ProductCategory/209` (🍼 Baby & toddler), `gid://shopify/ProductCategory/251` (🍽️ Food & drinks), `gid://shopify/ProductCategory/267` (⚽ Sporting goods), `gid://shopify/ProductCategory/285` (🎨 Arts & crafts)

**`storeLocation`** — `""` (🌐 Any location), `GLOBAL` (🌍 Global — all markets), `ENGLISH_SPEAKING` (🗣️ English-speaking), `EUROPE` (🇪🇺 Europe), `NORTH_AMERICA` (🌎 North America), `UK_IRELAND` (🇬🇧 UK & Ireland), `NORDICS` (❄️ Nordics), `OCEANIA` (🌏 Oceania), `US` (🇺🇸 United States), `GB` (🇬🇧 United Kingdom), `CA` (🇨🇦 Canada), `AU` (🇦🇺 Australia), `NZ` (🇳🇿 New Zealand), `IE` (🇮🇪 Ireland), `DE` (🇩🇪 Germany), `FR` (🇫🇷 France), `IT` (🇮🇹 Italy), `ES` (🇪🇸 Spain), `NL` (🇳🇱 Netherlands), `PL` (🇵🇱 Poland), `AT` (🇦🇹 Austria), `CH` (🇨🇭 Switzerland), `PT` (🇵🇹 Portugal), `SE` (🇸🇪 Sweden), `DK` (🇩🇰 Denmark), `FI` (🇫🇮 Finland)

**`shipsTo`** — `""` (🌐 Any country), `US` (🇺🇸 United States), `CA` (🇨🇦 Canada), `GB` (🇬🇧 United Kingdom), `AU` (🇦🇺 Australia), `DE` (🇩🇪 Germany), `FR` (🇫🇷 France), `IT` (🇮🇹 Italy), `ES` (🇪🇸 Spain), `NL` (🇳🇱 Netherlands), `BE` (🇧🇪 Belgium), `AT` (🇦🇹 Austria), `CH` (🇨🇭 Switzerland), `SE` (🇸🇪 Sweden), `DK` (🇩🇰 Denmark), `NO` (🇳🇴 Norway), `FI` (🇫🇮 Finland), `IE` (🇮🇪 Ireland), `PT` (🇵🇹 Portugal), `PL` (🇵🇱 Poland), `CZ` (🇨🇿 Czech Republic), `RO` (🇷🇴 Romania), `HU` (🇭🇺 Hungary), `GR` (🇬🇷 Greece), `HR` (🇭🇷 Croatia), `BG` (🇧🇬 Bulgaria), `SK` (🇸🇰 Slovakia), `SI` (🇸🇮 Slovenia), `LT` (🇱🇹 Lithuania), `LV` (🇱🇻 Latvia), `EE` (🇪🇪 Estonia), `IS` (🇮🇸 Iceland), `LU` (🇱🇺 Luxembourg), `NZ` (🇳🇿 New Zealand), `JP` (🇯🇵 Japan), `KR` (🇰🇷 South Korea), `SG` (🇸🇬 Singapore), `HK` (🇭🇰 Hong Kong), `TW` (🇹🇼 Taiwan), `MY` (🇲🇾 Malaysia), `PH` (🇵🇭 Philippines), `TH` (🇹🇭 Thailand), `ID` (🇮🇩 Indonesia), `VN` (🇻🇳 Vietnam), `IN` (🇮🇳 India), `BR` (🇧🇷 Brazil), `MX` (🇲🇽 Mexico), `CO` (🇨🇴 Colombia), `AR` (🇦🇷 Argentina), `CL` (🇨🇱 Chile), `ZA` (🇿🇦 South Africa), `AE` (🇦🇪 United Arab Emirates), `SA` (🇸🇦 Saudi Arabia), `IL` (🇮🇱 Israel), `TR` (🇹🇷 Turkey), `NG` (🇳🇬 Nigeria), `EG` (🇪🇬 Egypt), `KE` (🇰🇪 Kenya)

</details>

#### Example input

```json
{
    "searchQueries": ["wireless headphones", "organic coffee"],
    "category": "",
    "storeLocation": "US",
    "maxItems": 50,
    "skipPreviouslyScraped": true,
    "priceMin": 20,
    "priceMax": 100,
    "onSale": false,
    "inStock": true,
    "shipsFrom": false,
    "shipsTo": "",
    "proxyConfiguration": { "useApifyProxy": false },
    "maxRetries": 3,
    "maxScanned": 20000
}
```

### ⬆️ Output

Every store is pushed to the dataset as typed, normalized JSON the moment it's enriched — the field names stay the same across every run. Results are available as full JSON, through the per-section dataset views (Overview, Contacts & Address, Ratings & Reviews, Sample Products), or as a CSV export.

#### Example output

```json
{
    "id": "1235",
    "name": "JLab",
    "websiteUrl": "https://www.jlab.com?utm_source=shop_app",
    "myshopifyDomain": "jlabgrabbag.myshopify.com",
    "shareUrl": "https://shop.app/m/jlab?utm_source=shop_app",
    "address": {
        "address1": "5927 Landau Court",
        "address2": "",
        "city": "Carlsbad",
        "zone": "California",
        "zoneCode": "CA",
        "country": "US",
        "postalCode": "92008",
        "company": null,
        "phone": null,
        "formatted": ["5927 Landau Court", "Carlsbad, California 92008", "United States"]
    },
    "contacts": [
        { "method": "web", "target": "https://www.jlab.com?utm_source=shop_app" },
        { "method": "facebook", "target": "https://www.facebook.com/JLabTech/" },
        { "method": "instagram", "target": "https://www.instagram.com/jlabaudio" },
        { "method": "email", "target": "support@jlab.com" },
        { "method": "phone", "target": "405-445-7219" }
    ],
    "rating": 4.6127,
    "totalProductRatings": 7820,
    "totalProductReviews": 3932,
    "sampleProducts": [
        {
            "title": "GO POP+ True Wireless Earbuds Black",
            "price": 24.99,
            "currency": "USD",
            "url": "https://www.jlab.com/products/go-pop-true-wireless-earbuds-black?utm_source=shop_app",
            "imageUrl": "https://cdn.shopify.com/s/files/1/0240/9337/files/GOPop_Black3.jpg?v=1762446393"
        }
    ],
    "scrapedAt": "2026-09-01T07:37:40.114187+00:00",
    "searchQuery": "wireless headphones"
}
```

### ⚙️ How does it work?

Every run starts by fetching shop.app's live category taxonomy and endpoint paths from its own web bundle, rather than hardcoded values, so the Actor keeps working if shop.app renames a route. A one-time guest session is then minted using a real, visible Chrome browser under a virtual display — shop.app's guest sign-in endpoint rejects both plain HTTP clients and headless browsers, so a genuinely non-headless session is required. Those cookies are handed to a fast, browser-impersonating HTTP client for every search and enrichment call, each carrying the same headers shop.app's own web client sends. If shop.app blocks a request, the Actor escalates through Datacenter and then Residential proxies automatically. Only data shop.app already serves publicly is returned, and output field names stay stable run over run, even if shop.app changes its layout.

### 🔌 Integrations

Shopify Store Leads Scraper - Emails, Phones & Ratings runs on the Apify platform, so it works with anything that can call the Apify API — your own scripts, no-code automation tools, and AI agent frameworks.

#### Calling Shopify Store Leads Scraper - Emails, Phones & Ratings programmatically

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("testt0/shopify-store-leads-scraper-emails-phones-ratings").call(
    run_input={"searchQueries": ["wireless headphones"], "maxItems": 20}
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request to the Apify API.

#### MCP integration for AI agents

This Actor is reachable through Apify's own hosted MCP server — no extra deployment needed. Point an MCP-compatible client at `https://mcp.apify.com?tools=testt0/shopify-store-leads-scraper-emails-phones-ratings`, or run it locally with `npx @apify/actors-mcp-server --tools actors,docs,testt0/shopify-store-leads-scraper-emails-phones-ratings` and an `APIFY_TOKEN` environment variable. Compatible clients include Claude Desktop, Claude Code, Cursor, and VS Code (GitHub Copilot).

#### No-code tools (n8n, Make, LangChain)

- **n8n** — install `@apify/n8n-nodes-apify` and use its **Run Actor** action (with this Actor's ID) followed by **Get dataset items**, or a plain HTTP Request node against the run-sync-get-dataset-items endpoint.
- **Make** — use an HTTP module to call the Actor's `run-sync-get-dataset-items` endpoint with your Apify API token, the same way any REST integration is wired into a Make scenario.
- **LangChain** — use `ApifyWrapper().call_actor(actor_id="testt0/shopify-store-leads-scraper-emails-phones-ratings", run_input={...}, dataset_mapping_function=...)` to run the Actor and load its dataset straight into a LangChain document loader for RAG.

### ⚖️ Is it legal to scrape Shopify store leads?

Scraping publicly available business information is generally legal in most jurisdictions, and Shopify Store Leads Scraper - Emails, Phones & Ratings returns only data merchants themselves chose to publish on shop.app — nothing behind a login. The `contacts` and `address` fields this Actor collects are store-level business records (a support inbox, a company phone line, a registered business address) rather than data about a named individual, so this falls under standard **terms-of-service and database-rights** considerations rather than GDPR/CCPA's personal-data regime. That said, a sole trader whose published "business" email or phone is also their personal one could still bring that specific record within scope of GDPR/CCPA depending on your jurisdiction and use — review your own use case accordingly. Consult legal counsel if your use case involves bulk storage of personal data.

### ❓ Frequently asked questions

#### What Shopify store fields does Shopify Store Leads Scraper - Emails, Phones & Ratings return?

The top fields are `contacts` (email, phone, social links), `address` (business address), `rating`/`totalProductRatings`/`totalProductReviews`, `sampleProducts`, and `websiteUrl`/`myshopifyDomain`. See What data can I extract above for the full list.

#### Does Shopify Store Leads Scraper - Emails, Phones & Ratings require a Shopify account or login?

No. The Actor mints its own guest session with shop.app internally — you don't need a Shopify account, a shop.app login, or an API key to run it.

#### How many Shopify stores can I extract in one run?

`maxItems` caps unique stores per search query at up to 100,000, and `searchQueries` accepts multiple keywords in one run, so the run-wide ceiling is roughly `maxItems × number of queries`. A `maxScanned` safety cap (up to 200,000 raw result rows per query) stops a hopeless keyword from scanning forever even if `maxItems` isn't reached.

#### What happens if a search query returns zero results?

That query is logged as "0 stores found" and the run moves on to the next one — it doesn't fail the whole run. If every query in a run returns nothing, the Actor logs a warning suggesting a broader keyword, fewer filters, or an explicit Residential proxy in case shop.app is blocking the run outright.

#### Can I scrape multiple Shopify stores at once?

Yes — `searchQueries` is a bulk array field. Add as many keywords as you like in one run; each is searched independently and every discovered store streams into the same dataset.

#### Does Shopify Store Leads Scraper - Emails, Phones & Ratings work with Claude, ChatGPT, and other AI agent tools?

Yes. It's reachable through Apify's hosted MCP server (see Integrations above) for MCP-native clients like Claude Desktop and Claude Code, and callable as a plain HTTP endpoint by any other agent framework, including ChatGPT's custom-tool/Actions setups.

#### Does Shopify Store Leads Scraper - Emails, Phones & Ratings avoid duplicate leads across runs?

Yes, if you turn on `skipPreviouslyScraped`. Each unique search (keyword + category + store location + ships-to combination) keeps its own history in a named key-value store, so a later run of the same search returns only stores it hasn't returned before; price, availability, and shipping-origin filters don't start a new history.

#### Does Shopify Store Leads Scraper - Emails, Phones & Ratings return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with consistent field names across runs — no HTML parsing, no selectors. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.

#### What happens when shop.app changes its layout or anti-bot system?

The Actor is maintained and its output field names stay stable. It also re-resolves its own endpoint paths and category taxonomy live at the start of every run rather than relying on hardcoded values, so it tolerates smaller shop.app changes (a renamed route, a new category) without needing a code update.

#### Can I use Shopify Store Leads Scraper - Emails, Phones & Ratings without managing proxies or browser infrastructure?

Yes. The Actor handles the one-time Chrome session mint (under a virtual display), the browser-impersonating HTTP client for search/enrichment calls, and the Direct → Datacenter → Residential proxy escalation itself — you only need to touch `proxyConfiguration` if you want to force a specific tier from the start.

#### Which Shopify store fields work best for AI training data and RAG indexing?

For RAG, index the high-information text fields: `name`, `address.formatted`, `contacts`, and `sampleProducts[].title`. For training data, the most consistently structured fields are `rating`, `totalProductRatings`, `totalProductReviews`, and `sampleProducts[].price` — all typed primitives (numbers, strings, or arrays of objects), never free-form HTML.

### 🔗 Related scrapers

| Scraper Name | What it extracts |
| --- | --- |
| Linkedin Profile Scraper with Email & Company Data | LinkedIn profiles enriched with contact emails and company details |
| LinkedIn People Profile Scraper | LinkedIn people-profile data |
| Naukri Job Scraper India Gulf Emails & 41 Fields | Job listings with recruiter emails across India and the Gulf |
| Y Combinator Scraper | Y Combinator startup company records |

### 💬 Your feedback

Found a bug or missing a field? Let us know — reach the Scraper Engine team at dev.scraperengine@gmail.com or open an issue from the Actor's page in Apify Store. Feedback on data quality and edge cases is always welcome.

# Actor input Schema

## `searchQueries` (type: `array`):

One or more product keywords to search for — each is scraped as its own independent search and results stream into the same dataset. Leave empty to discover stores by 📂 Category alone. Examples: <code>wireless headphones</code>, <code>organic coffee</code>, <code>yoga mat</code>.

## `category` (type: `string`):

Filter to stores selling in this product category. Works alone (discovers every store in the category) or combined with a search query above to narrow results. Applied to every query in this run.

## `storeLocation` (type: `string`):

Find stores <b>based in</b> a specific country or region. Stores that don't publish a business address are still included as likely matches. For non-English markets, search using local-language keywords above (e.g. <code>kerzen</code> instead of <code>candles</code>) for the best results.

## `maxItems` (type: `integer`):

Maximum number of unique stores to return for each search query above.

## `skipPreviouslyScraped` (type: `boolean`):

Continue where your last run for this same search left off — stores already returned before are skipped, so every run brings fresh leads. Each search (keyword + category + store location + ships-to combination) keeps its own history; price/availability/shipping-origin filters don't start a new one. Turn this on from your very first run.

## `priceMin` (type: `integer`):

Only discover stores selling products above this price (USD).

## `priceMax` (type: `integer`):

Only discover stores selling products below this price (USD).

## `onSale` (type: `boolean`):

Only discover stores with products currently on sale.

## `inStock` (type: `boolean`):

Only discover stores with products currently in stock. This matches shop.app's own default search behaviour.

## `shipsFrom` (type: `boolean`):

Only discover stores that ship FROM the 📍 Store Location selected above. Has no effect if Store Location is left as "Any location".

## `shipsTo` (type: `string`):

Only discover stores that ship TO a specific destination country.

## `proxyConfiguration` (type: `object`):

🟢 Default = no proxy (direct connection to shop.app), which works for most runs. If shop.app starts rejecting requests, the Actor automatically escalates itself: Direct ➜ 🖥️ Datacenter proxy ➜ 🏠 Residential proxy (retried up to 3× with a fresh IP), then stays on residential for the rest of the run. Every switch is logged clearly. Override this only to force a specific proxy from the start.

## `maxRetries` (type: `integer`):

How many times to retry a single blocked/failed request (on the same proxy tier) before the Actor escalates to the next proxy tier.

## `maxScanned` (type: `integer`):

Safety cap on how many raw search result rows a single query may scan through before giving up, even if 'Max Stores' hasn't been reached (protects against a runaway search on a hopeless keyword).

## Actor input object example

```json
{
  "searchQueries": [
    "wireless headphones"
  ],
  "category": "",
  "storeLocation": "",
  "maxItems": 10,
  "skipPreviouslyScraped": false,
  "onSale": false,
  "inStock": true,
  "shipsFrom": false,
  "shipsTo": "",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRetries": 3,
  "maxScanned": 20000
}
```

# Actor output Schema

## `results` (type: `string`):

Every scraped store, across every search query, in the order it was collected.

## `overview` (type: `string`):

Quick-glance identity, rating, and website per store.

## `contacts` (type: `string`):

Email, phone, social links, and business address per store.

## `ratings` (type: `string`):

Review analytics per store.

## `products` (type: `string`):

Sample products sold by each store.

## `csv` (type: `string`):

All results exported as CSV.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "wireless headphones"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper-engine/shopify-store-leads-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["wireless headphones"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scraper-engine/shopify-store-leads-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "wireless headphones"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scraper-engine/shopify-store-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraper-engine/shopify-store-leads-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3lZxoWmemq54brVAZ/builds/wY9OHKqguOGgE2ghB/openapi.json
