# Shopify Store Leads — Catalog Size, Apps, Contacts (`autofacts/shopify-store-leads`) Actor

Find and qualify Shopify stores, or enrich domains you own. Each lead returns catalog size, price band, theme, installed apps, published policies, new products a month, emails, phones and socials. Filter by country, category, keyword, size, ships-to, price or apps. You pay only for rows you keep.

- **URL**: https://apify.com/autofacts/shopify-store-leads.md
- **Developed by:** [Richard Feng](https://apify.com/autofacts) (community)
- **Categories:** Lead generation, E-commerce, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 1,000 qualified stores

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shopify Store Leads — Catalog Size, Apps, Contacts

[![Shopify store leads, qualified: store size, installed apps, publishing activity and ratings, with business emails, phones and addresses. Pay only for stores that match.](https://api.apify.com/v2/key-value-stores/pbstlDhlpdg9ufpcn/records/readme-hero-v2.png)](https://console.apify.com/actors/pU2hf0UhalIpjJFzh/input)

**Shopify store leads you can qualify before you reach out.** Every row is one store: its
business emails, phone numbers, social profiles and address — and how big it is, what it
runs, and whether it is still selling. Find stores by what they sell, where they are and
what they have installed, or paste the domains you already have. **You pay only for stores
that match your filters.**

### Why choose this Actor?

**Know a store before you pitch it.** Most Shopify lead lists tell you a store exists and
hand you an email address. This one also returns the product count, the price band, the
product types and vendors, the theme and the installed apps, how many new products the
store publishes a month and how many days since its last. A 6,500-product catalog and a
13-product boutique look the same in a list of emails; here they don't.

**Contacts in the same row.** Business emails, phone numbers and social profiles from the
store's page on the Shop app, its storefront and its own contact page — plus its business
address and its Shop app rating. Every address the store publishes — `info@`, `hey@`,
`kundenservice@` alike — except the ones nobody reads, like `no-reply@`.

**Filter on what your pitch depends on.** Country, product category, keyword, catalog size,
average price, the countries a store ships to, stock, recent publishing, the apps a store
runs — or has *not* installed yet — the social networks it links, and whether it publishes
an email or a phone number. A keyword or a category is searched on the Shop app, Shopify's
marketplace, so you find stores by what they actually sell.

**Pay only for stores that match.** A store your filters reject is never returned and never
charged, and a store reached twice in one run is charged once. $5.00 per 1,000 stores on
the Free plan, down to $4.50 on Business.

**[Try it on your own stores →](https://console.apify.com/actors/pU2hf0UhalIpjJFzh/input)**

### 🚀 Quick start

1. Click **Try for free**. The input opens prefilled with a few well-known stores: start it
   as it is, and within a minute you have rows to look at.
2. To profile stores you already know, paste their domains into **Store URLs** — one per
   line; `gorjana.com` and `https://gorjana.com` both work.
3. To find new stores instead, leave **Store URLs** empty and set a **Keyword** or a
   **Product category**, then any filters — **Countries**, **Minimum products**,
   **Published a product within (days)**, the apps a store should or should not run.
4. Set **Maximum stores**. It caps how many rows the run returns, and so the most it can
   charge you.
5. Click **Start**, then download the results from the **Storage** tab as JSON, CSV, Excel
   or XML — or pull them from the API.

Start small, check the rows look how you expect, then raise **Maximum stores**.

### 💡 What people use it for

**Sell to stores that run an app you integrate with.** Stores running Klaviyo or Okendo
that link an Instagram account, in the US and the UK:

```json
{ "hasApps": ["klaviyo", "okendo"], "hasSocials": ["instagram"], "countries": ["US", "GB"], "maxItems": 200 }
```

**Find stores that don't show a competitor's app yet.** Stores on Klaviyo with no reviews
app on their storefront:

```json
{ "hasApps": ["klaviyo"], "excludeApps": ["judge-me", "loox", "okendo", "stamped", "yotpo"], "countries": ["US"], "maxItems": 200 }
```

**Build a list of active stores in a niche.** US jewellery stores with a real catalog that
published a product in the last 90 days:

```json
{ "countries": ["US"], "category": "jewelry", "minProducts": 50, "activeWithinDays": 90, "maxItems": 500 }
```

**Find stores by what they sell**, each with its Shop app rating and business address:

```json
{ "query": "coffee", "countries": ["US"], "maxItems": 100 }
```

**Qualify mid-market stores that ship to you, are trading, and can be contacted:**

```json
{ "shipsToCountries": ["US"], "minAvgPrice": 5000, "maxAvgPrice": 30000, "inStockOnly": true, "requireEmail": true, "maxItems": 200 }
```

**Profile stores you already know:**

```json
{ "storeUrls": ["gorjana.com", "allbirds.com"], "maxItems": 10 }
```

### 📋 Input

Everything is optional. With a `query` or a `category`, the stores come from the Shop app's
search for it, and from nowhere else. With neither, the Actor discovers stores from its
built-in list of 6,542 verified stores, then from Common Crawl. Either way it looks each
store it keeps up on the Shop app.

| Field | Type | Default | What it does |
|---|---|---|---|
| `storeUrls` | array | — | Domains to profile. Set this and discovery is skipped entirely. |
| `query` | string | — | Find stores selling this: searched on the Shop app, which is then the only source of stores. With `useShopApp` off, or on your own `storeUrls`, it is matched against store name, description and domain instead. |
| `category` | string | — | Product category. With no `query`, searched on the Shop app, which is then the only source of stores; otherwise matched against the store's own product types. |
| `countries` | array | — | Two-letter country codes, e.g. `["US","GB"]`. |
| `minProducts` | integer | — | Skip stores with fewer products than this. |
| `maxProducts` | integer | — | Skip stores with more products than this. |
| `activeWithinDays` | integer | — | Only stores that published a product this recently. |
| `excludeKeywords` | array | — | Drop stores matching any of these words. |
| `shipsToCountries` | array | — | Only stores shipping to at least one of these countries. |
| `minAvgPrice` | integer | — | Minimum average product price, in minor units — `5000` is `50.00`. |
| `maxAvgPrice` | integer | — | Maximum average product price, in minor units. |
| `inStockOnly` | boolean | `false` | Only stores with something actually in stock. |
| `hasApps` | array | — | Only stores running these apps, by handle — `klaviyo`, `judge-me`, `okendo`. |
| `appMatchMode` | string | `any` | Whether `hasApps` means any of them or all of them. |
| `excludeApps` | array | — | Drop stores running any of these apps — find stores that have *not* installed a competitor yet. |
| `hasSocials` | array | — | Only stores linking at least one of these networks — `instagram`, `tiktok`, `facebook`. |
| `requireEmail` | boolean | `false` | Only stores that publish a business email address. |
| `requirePhone` | boolean | `false` | Only stores that publish a phone number. |
| `maxItems` | integer | `100` | Maximum stores to return. The hard cap on what the run can charge. To cap spend in currency instead, set **Maximum total charge** in the run options — the platform enforces it. |
| `includeCatalog` | boolean | `true` | Product/collection counts, price band, types, vendors. |
| `includeContacts` | boolean | `true` | Business emails, phones and social profiles, and the business address. The ones on the store's Shop app page come first; the storefront fills in the rest. |
| `includeTechStack` | boolean | `true` | Theme, installed apps, accepted card brands. |
| `useShopApp` | boolean | `true` | Use the Shop app. With a `query`, or a `category` when there is no `query`, its product search is where the stores come from. Every store that passes your filters is then found on the Shop app — by that search, or by its own name — for its rating and, with `includeContacts`, its business address and the contacts it lists there. Set `false` to read only the stores' own storefronts, found through the seed and Common Crawl. |
| `useSeed` | boolean | `true` | Examine the built-in list of verified stores before Common Crawl, when there is no `query` or `category` for the Shop app to search. |
| `ccIndex` | string | — | Pin a specific Common Crawl index. Leave empty for the newest. |
| `proxy` | object | Apify Proxy | Leave this on — see the FAQ. |

### 📤 Output

One row per store, 40 fields in seven groups:

| Group | Fields |
|---|---|
| Identity and location | `url`, `domain`, `myshopifyDomain`, `name`, `description`, `country`, `province`, `city`, `currency`, `languages`, `shipsToCountries` |
| Catalog | `productCount`, `collectionCount`, `priceMin`, `priceMax`, `priceAvg`, `pricedFrom`, `productTypes`, `vendors`, `sizeBand` |
| Activity | `newestProductUTC`, `oldestProductUTC`, `daysSinceLastProduct`, `isActive`, `productsPerMonth` |
| Tech stack | `theme`, `apps`, `policies`, `announcementBarText`, `cardBrands`, `offersShopPayInstallments` |
| Contacts | `emails`, `phones`, `socials` |
| From the Shop app | `rating` — `average`, `ratingCount`, `reviewCount` — and `address` |
| Provenance | `discoveredVia`, `scrapedUTC` |

Real output, trimmed for length:

```json
{
  "url": "https://www.gorjana.com/",
  "domain": "www.gorjana.com",
  "myshopifyDomain": "gorjana.myshopify.com",
  "name": "gorjana",
  "description": "Complete your look with jewelry designed to layer...",
  "country": "US",
  "province": "California",
  "city": "Laguna Beach",
  "address": ["3275 Laguna Canyon Rd Ste R1", "Laguna Beach, California 92651", "United States"],
  "currency": "USD",
  "languages": ["en"],
  "shipsToCountries": ["AC", "AD", "AE", "..."],
  "catalog": {
    "productCount": 983,
    "collectionCount": 575,
    "priceMin": 3000,
    "priceMax": 599000,
    "priceAvg": 17884,
    "pricedFrom": 250,
    "productTypes": ["Anklets", "Bracelets", "Charms", "Earrings", "Gift Cards", "Hand Chains", "Necklaces", "Rings"],
    "vendors": ["Bespoke", "Fine", "Layering Set", "..."],
    "sizeBand": "medium"
  },
  "activity": {
    "newestProductUTC": 1790111736,
    "oldestProductUTC": 1767325861,
    "daysSinceLastProduct": 1,
    "isActive": true,
    "productsPerMonth": 28.9
  },
  "theme": { "name": "[RELEASE] 5.2.0", "id": 166571606147, "version": "" },
  "apps": [{ "handle": "klaviyo", "name": "Klaviyo" }, { "handle": "okendo", "name": "Okendo" }],
  "policies": [],
  "announcementBarText": null,
  "cardBrands": ["visa", "master", "american_express", "discover"],
  "offersShopPayInstallments": true,
  "contacts": {
    "emails": ["customercare@gorjana.com"],
    "phones": ["8668290030"],
    "socials": {
      "x": "https://twitter.com/gorjana_brand",
      "facebook": "https://www.facebook.com/gorjanabrand",
      "instagram": "https://www.instagram.com/gorjana",
      "youtube": "https://www.youtube.com/@gorjanabrand",
      "tiktok": "https://www.tiktok.com/@gorjana",
      "pinterest": "https://www.pinterest.com/gorjanabrand"
    }
  },
  "rating": { "average": 4.81, "ratingCount": 18510, "reviewCount": 4610 },
  "discoveredVia": "input",
  "scrapedUTC": 1790214009
}
```

Two conventions worth knowing: **prices are integers in minor units**, so `17884` means
`$178.84`, and **timestamps are epoch seconds**.

`productsPerMonth` is what separates a store publishing 30 products a month from one that
published its last 30 over four years — `isActive` calls both of them active.

`policies` is empty for this store because gorjana links its policies as ordinary pages
rather than at Shopify's canonical `/policies/…` URLs, which is worth knowing before you
filter on it. Across a sample of ordinary stores about eight in ten use the canonical form
and return a list like `["refund-policy", "shipping-policy", "terms-of-service"]` — but
**large direct-to-consumer brands mostly do not**: of nine well-known ones checked, one
published canonical policy URLs. Read an empty list as "not published at the canonical
URL", never as "this store has no refund policy".

`announcementBarText` is the storefront's announcement bar, verbatim and in whatever
language the merchant wrote it in — `"FREE SHIPPING FOR ORDERS OVER £70"`,
`"DESCUENTO DEL 10% PARA COMPRAS SUPERIORES A 80€"`, `"Final Sale. No Returns or
Exchanges."` It tells you what the store is promoting right now, which is the difference
between a shop that is trading and one that is merely online. Null for gorjana, and for
about four stores in ten.

`rating` is the store's rating on the Shop app, built by Shop from its own reviews and
approved review apps, so no storefront carries it. `address` is the business address a
store gives the Shop app, one entry per line as the Shop app formats it: street, then town,
region and postcode, then country. It is not split into parts, because the layout is the
country's. The Actor finds every store it keeps on the Shop app: a store the Shop app's
search found arrives with its rating, and any other — like gorjana here, named in
`storeUrls` — is looked up there by its own name and matched on its Shopify id. gorjana's
Shop app page also gave the phone number and the Pinterest profile above: its homepage
prints the number without linking it and does not link Pinterest at all, so the storefront
alone gave neither. Of 30 coffee stores found through the Shop app's search on 2026-09-23,
all 30 carried a rating, 25 an address, 24 an email and 23 a phone.

### 💰 Pricing

Pay per store returned, with no monthly fee. The price per store falls with your Apify
plan:

| Apify plan | Per 1,000 stores | Per store |
|---|---:|---:|
| Free | $5.00 | $0.0050 |
| Starter | $4.80 | $0.0048 |
| Scale | $4.60 | $0.0046 |
| Business and above | $4.50 | $0.0045 |

- **A store your filters reject is never charged** — it is never returned. You pay for the
  rows you keep.
- **A store reached twice in one run is charged once.**
- **Two ways to cap a run:** **Maximum stores** caps the rows and so the charge, and
  **Maximum total charge** in the run options caps it in dollars — the platform enforces
  it.
- Each run also carries a start fee of $0.00005.

### ⚠️ What this Actor does not do

Stated up front so you can judge fit before paying.

- **The price band is a sample, not a census.** Computed from up to 250 products;
  `catalog.pricedFrom` tells you how many were used. Product and collection counts are
  exact — the store reports those itself.
- **App detection sees the public storefront only.** A purely back-office app with no
  asset on the page is invisible. A detected app is real; an undetected one is not proof
  of absence.
- **Contacts are what the store publishes, as it publishes them.** Every email address on
  its storefront, its Shop app page or its contact page is kept — a named person's too, when
  the store lists one — except `no-reply@` addresses and the placeholders themes and apps
  ship with. No job titles or LinkedIn profiles: nothing the store did not publish itself.
- **A keyword run finds what the Shop app's search finds, and nothing more.** With a
  `query` or `category`, the stores come from that search alone, custom domains included;
  a store the Shop app does not list, or does not show for that word, is not found — you
  can still profile it directly via `storeUrls`. Without either, discovery walks the
  built-in list and Common Crawl, which finds stores through their `.myshopify.com`
  address: roughly half have a custom domain configured, and a store only ever crawled at
  its custom domain may not be discoverable.
- **`rating` and `address` come from the Shop app.** A store its search found carries
  them; any other is looked up by its own name and matched on its Shopify id. A store the
  Shop app does not list under that name has `rating: null` and `address: []` — as,
  sometimes, does one whose products do not ship to where the request comes from, which the
  Shop app's search leaves out. So does every store with `useShopApp` off.
- **Shop app requests are made one at a time, each from its own IP.** A stored store costs
  one when the Shop app's search found it, two otherwise — a lookup, then its page when
  `includeContacts` is on — and the Actor spaces them half a second apart. Stores rejected by
  your filters never cost one. A refused request is sent again from another IP. If the
  Shop app still stops answering a store's requests, the run carries on and the rest of its
  stores come back without the Shop app's data; if it stops answering the search itself, a
  keyword run ends with the stores it has and says why.
- **`policies` counts Shopify's canonical policy pages only.** A store that hand-builds a
  `/pages/refund-policy` instead is reported as having none. Empty means "not published at
  the canonical URL", not "this store has no refund policy".
- **`announcementBarText` is the bar's text, not a parsed promotion.** There is no
  free-shipping threshold, discount percentage or promo-code field, and that is measured,
  not an omission: the copy is written in the store's own language, so an English pattern
  would report every non-English store as running no promotion — and a percent-off pattern
  run over a storefront matches product prices, not promotions. You get the sentence; read
  it yourself. **How much of a rotating bar you get depends on the theme.** Where each
  slide sits in its own element you get one message; where the theme puts them all in one
  element you get them all, joined — `tentree.com` returns `"FREE SHIPPING ON ORDERS OVER
  $100 FREE SHIPPING ENDS MONDAY. CODE: FREESHIP DEEPEST DISCOUNTS: 30-50% OFF SHOP NOW
  EVERY ITEM PLANTS 10 TREES"`, which is four promotions at once. Where a theme splits one
  message across nested elements you get the innermost piece. Null means the store has no
  bar, or fills it in after the page renders.
- **`productsPerMonth` is measured over the sampled window.** For a store with more
  products than the sample it is the recent rate; for a smaller store it is the lifetime
  average. It is `null` when the sample is too thin to support a rate.
- **The price filters compare each store in its own currency.** `minAvgPrice` is matched
  against the store's own prices, so a run spanning several currencies is comparing
  numbers, not value. Pair them with `countries` when that matters.
- **Stores that don't answer are skipped, not guessed at** — and cost you nothing.

### 🧰 Works well with

| Actor | Use it for |
|---|---|
| [Shopify Scraper](https://apify.com/autofacts/shopify) | Products and collections from a store this Actor found. The natural next step: qualify the store here, then pull its catalog there. |
| [Schema Markup Scraper & SEO Auditor](https://apify.com/autofacts/metadata-scraper) | Audit the structured data and SEO of any store in your list. |
| [Anytime Mailbox Scraper](https://apify.com/autofacts/anytime-mailbox-scraper-virtual-mailbox-locations-cmra) | Business locations and CMRA records — another lead source to enrich the same list. |
| [Indeed Jobs Scraper](https://apify.com/autofacts/indeed-jobs-scraper-companies-reviews-salaries) | Hiring signals on the companies you qualify. |
| [WooCommerce Scraper](https://apify.com/autofacts/woocommerce-scraper) | Catalogs for the WooCommerce stores in your list. |

All of them: [apify.com/autofacts](https://apify.com/autofacts)

### ❓ FAQ

**Do I need to configure the proxy?**
No — leave it on the default. Shopify limits requests per IP address, so the Actor
rotates through Apify Proxy automatically, and sends a refused request again from another
address. Turning the proxy off makes every store share one address and get refused
together.

**How fresh is the data?**
Every run reads each store live — its storefront, its catalog and its Shop app page — at
the time of the run. Nothing is served from a cache, and `scrapedUTC` records when each row
was read.

**Is scraping these stores legal?**
Everything returned is published openly for anyone to read — no login, no paywall — by the
store on its own storefront, or by the merchant on its Shop app page. Contacts are the
addresses the store chose to publish, which can include a named person's where the store
lists one. The Shop app
is Shopify's consumer marketplace, and its terms restrict automated access; the Actor reads
it by default, and `useShopApp: false` keeps a run to the stores' own storefronts. You are
responsible for how you use the output, including under GDPR, CAN-SPAM and local marketing
rules.

**How many stores can I get?**
As many as `maxItems` allows and your filters leave. With a `query` or `category`, that is
also as many as the Shop app's search has for the word — up to about 10,000 candidates a
run; the run says so when the search runs out first. The Actor stops as soon as it has
stored what you asked for.

**Can I get results automatically?**
Yes. Schedule the Actor, or call it from the Apify API, or connect it to Make, Zapier,
Slack, Google Sheets and the other Apify integrations. Results can also be pushed to a
webhook when a run finishes.

**Why are some fields empty?**
Not every store publishes everything. A store with no public email returns an empty
`contacts.emails` rather than a guess. Empty means "not published", not "not checked".

**Can you add a field or a filter?**
Yes — open an issue on the Actor and describe what you need.

### 🤖 Use with AI agents

This Actor is callable as a tool by any MCP-capable agent — Claude, Cursor, VS Code — or by your
own code, with no wrapper and nothing extra to deploy.

**Connect over MCP**

```
https://mcp.apify.com?tools=autofacts/shopify-store-leads
```

In a client that reads an `mcpServers` configuration block:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=autofacts/shopify-store-leads",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

The agent reads this Actor's parameters and their descriptions straight from the input
schema, and the hosted server infers the result field types from the dataset schema — so a
model knows what to send and what comes back before it ever calls anything.

**Or call the API directly**

```bash
curl -X POST "https://api.apify.com/v2/acts/autofacts~shopify-store-leads/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"storeUrls": ["gorjana.com", "tentree.com", "ayvii.com"]}'
```

The response body is the dataset records described above.

# Changelog

This Actor's version history is a separate document: https://apify.com/autofacts/shopify-store-leads/changelog.md

# Actor input Schema

## `storeUrls` (type: `array`):

Stores you already know, to enrich directly. When this is set, discovery is skipped entirely and only these stores are processed. Accepts a full URL or a bare domain.

## `query` (type: `string`):

Find stores selling this. With 'Use the Shop app' on, the default, the stores come from the Shop app's search for it, and from nowhere else. With it off, or on stores you list yourself, it keeps only stores whose name, description or domain contains this text — checked at the first request, so non-matching stores cost nothing.

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

Find stores selling this kind of product, e.g. 'jewelry', 'coffee', 'skincare'. With 'Use the Shop app' on, the default, and no keyword, the stores come from the Shop app's search for it, and from nowhere else. Otherwise it keeps only stores whose own product types contain this text.

## `countries` (type: `array`):

Keep only stores based in these countries. Two-letter ISO codes, e.g. US, GB, AU.

## `minProducts` (type: `integer`):

Keep only stores with at least this many published products. Evaluated on the first request.

## `maxProducts` (type: `integer`):

Keep only stores with at most this many published products.

## `activeWithinDays` (type: `integer`):

Keep only stores that published a product in the last N days — the cheapest way to drop abandoned storefronts.

## `excludeKeywords` (type: `array`):

Drop stores whose name, description or domain contains any of these.

## `shipsToCountries` (type: `array`):

Keep only stores that ship to at least one of these countries. Two-letter codes. Decided from /meta.json, so a store that does not ship where you sell is dropped for a single request.

## `minAvgPrice` (type: `integer`):

Keep only stores whose average product price is at least this, in minor units of the store's own currency — 5000 means 50.00. Sampled from up to 250 products.

## `maxAvgPrice` (type: `integer`):

Keep only stores whose average product price is at most this, in minor units of the store's own currency — 5000 means 50.00.

## `inStockOnly` (type: `boolean`):

Keep only stores with at least one in-stock product in the sample. Drops abandoned and sold-out storefronts.

## `hasApps` (type: `array`):

Keep only stores running at least one of these apps, by handle — for example klaviyo, okendo, judgeme, rechargepayments. Detected from the public storefront.

## `appMatchMode` (type: `string`):

How 'Runs any of these apps' matches: any of them, or all of them.

## `excludeApps` (type: `array`):

Drop stores running any of these apps, by handle. Useful for finding stores that have NOT yet installed a competitor to what you sell.

## `hasSocials` (type: `array`):

Keep only stores linking at least one of these networks: instagram, tiktok, facebook, youtube, x, pinterest, linkedin.

## `requireEmail` (type: `boolean`):

Keep only stores that publish a business email address.

## `requirePhone` (type: `boolean`):

Keep only stores that publish a phone number.

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

Stop after storing this many stores. This is the hard cap on what the run can charge.

## `includeCatalog` (type: `boolean`):

Price band, product types and vendors. Costs one extra request per store; the product and collection counts are returned either way.

## `includeContacts` (type: `boolean`):

The email addresses, phone numbers and social profiles a store publishes, and its business address. Every published email address is kept except no-reply ones. With 'Use the Shop app' on, the default, the contacts a store lists on its Shop app page come first, with its business address, and the storefront fills in the rest.

## `includeTechStack` (type: `boolean`):

Storefront theme and the third-party apps detectable from the page's own assets.

## `useShopApp` (type: `boolean`):

Use the Shop app, Shopify's marketplace. With a keyword, or a product category when no keyword is set, its product search is where the stores come from. Every store that passes your filters is then found on the Shop app, by the search or by its own name, for its Shop app rating and, with contacts included, the business address and contacts it lists there. The stores' own pages fill in the rest. Turn off to read only the stores' own storefronts, found through the built-in seed and Common Crawl; the Shop app's terms restrict automated access.

## `useSeed` (type: `boolean`):

Examine the bundled list of known-good Shopify stores before falling back to Common Crawl, when there is no keyword or category for the Shop app to search. Makes short runs fast.

## `ccIndex` (type: `string`):

Which Common Crawl index to discover from, e.g. CC-MAIN-2026-34. Leave empty to use the newest available — the index is republished monthly and a pinned value stops refreshing the seed.

## `proxy` (type: `object`):

Used for every request the actor makes. Shopify rate-limits /meta.json per client IP, so rotation matters more than reputation here: the automatic Apify Proxy is enough. Leave it on — running without a proxy means sharing one egress IP with every other actor on the platform and being rate-limited as a group. No proxy group is requested, so the run uses whichever groups your own account has.

## `previousDatasetId` (type: `string`):

Reserved name, accepted and ignored. Hidden from the form because it does nothing: change tracking was evaluated and deliberately not built. The name is kept so adding it later is not a breaking input change.

## Actor input object example

```json
{
  "storeUrls": [
    "gorjana.com",
    "tentree.com",
    "ayvii.com"
  ],
  "shipsToCountries": [
    "US"
  ],
  "inStockOnly": false,
  "appMatchMode": "any",
  "requireEmail": false,
  "requirePhone": false,
  "maxItems": 100,
  "includeCatalog": true,
  "includeContacts": true,
  "includeTechStack": true,
  "useShopApp": true,
  "useSeed": true,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `stores` (type: `string`):

One row per store: identity, catalog, activity, tech stack and contacts.

# 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 = {
    "storeUrls": [
        "gorjana.com",
        "tentree.com",
        "ayvii.com"
    ],
    "shipsToCountries": [
        "US"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("autofacts/shopify-store-leads").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 = {
    "storeUrls": [
        "gorjana.com",
        "tentree.com",
        "ayvii.com",
    ],
    "shipsToCountries": ["US"],
}

# Run the Actor and wait for it to finish
run = client.actor("autofacts/shopify-store-leads").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 '{
  "storeUrls": [
    "gorjana.com",
    "tentree.com",
    "ayvii.com"
  ],
  "shipsToCountries": [
    "US"
  ]
}' |
apify call autofacts/shopify-store-leads --silent --output-dataset

```

## MCP server setup

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

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/pU2hf0UhalIpjJFzh/builds/wb25UKrHM11efXXvu/openapi.json
