# Shopify Store Leads Finder (Emails, Phones, Socials) (`steadyscrape/shopify-store-leads`) Actor

Finds Shopify stores by what they sell (or enriches your list of store domains): emails, phones, address, VAT number, social profiles, location, catalog size, newest product, price range, theme and installed apps. Pay per store lead; not-Shopify, closed and password-protected domains are free.

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

## Pricing

$3.00 / 1,000 store leads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Finder — emails, phones and socials of Shopify stores

Find **Shopify stores by what they sell** — `organic coffee`, `yoga mat`, `dog collar` — or **enrich a list of store
domains you already have**. Every store comes with its **public emails, phone numbers, contact page, legal name, business
address, VAT and company numbers, Instagram / Facebook / TikTok / YouTube / Pinterest / X / LinkedIn profiles, city and
country, currency, catalog size, newest product date, price range, product types, Shopify theme and installed apps**
(Klaviyo, Judge.me, Recharge, Gorgias, Okendo, Yotpo…).

**You only pay for store leads.** Domains that are not Shopify, closed or password-protected are free rows.

### Who it is for

- **Agencies selling to e-commerce brands** (email marketing, ads, CRO, SEO, design): prospect lists by niche and country,
  with the email and the apps each store already uses.
- **Shopify app and theme developers**: find stores running a competitor app or an old theme version.
- **Wholesalers, suppliers and marketplaces**: find retailers of a product category, with their price range.
- **Market researchers**: how many stores sell a product, where they are based, how big their catalogs are.

### How it works

1. You give **search terms** (what the stores sell) and/or a **list of store domains**.
2. Each search term is looked up in **Shop**, Shopify's own product catalog, through its public agent endpoint (the
   `search_catalog` tool — nothing else is ever called: no cart, no checkout). Every product found names the store that
   sells it, so a page of 50 products gives about 15–25 different stores.
3. Each store is then read from its own storefront, the pages Shopify serves to any visitor: `/meta.json` (name,
   location, currency, catalog size, countries it ships to), its **contact-information policy** (legal name, address,
   phone, email, VAT number), its newest products, its **homepage** (emails, phones, social profiles, theme, apps) and
   its **contact page** (more emails).
4. A store found by two search terms (or also in your domain list) is delivered and charged once.
5. One free summary row per search term says how many products and stores Shop returned and where each store went.

Measured on 2026-10-20: **"organic coffee" — 443 products from 148 stores; 25 of the first 30 stores published an email**
(17 on the homepage or policy, 8 more only on the contact page).

### Input example

```json
{
    "searchTerms": ["organic coffee", "specialty coffee beans"],
    "storeCountry": "US",
    "maxStores": 200,
    "requireEmail": true,
    "onlyNewStores": true
}
```

Enrich your own list:

```json
{
    "domains": ["puritycoffee.com", "https://www.cafebritt.com", "nzxx1a-ye.myshopify.com"]
}
```

| Field | What it does |
|---|---|
| `searchTerms` | Product keywords. Each reaches up to ~500 products (Shop's limit per search), usually 100–150 stores. |
| `domains` | Shopify stores you already have, as domains, links or `.myshopify.com` addresses. |
| `storeCountry` | Only stores based in this country (Shop filters products shipping from it; each store's registered country is checked). |
| `shipsTo` | Only products that ship to this country, wherever the store is based. |
| `maxStores` | Most store leads delivered (and charged) in the run. Default 50. |
| `requireEmail` | Only stores with at least one public email; the others are skipped for free. |
| `onlyNewStores` | Skip stores delivered to you in earlier runs with this option on: schedule it and get only new leads. |

### Output example

A real row (Purity Coffee, found by "organic coffee"):

```json
{
    "rowType": "store",
    "name": "Purity Coffee",
    "storeUrl": "https://puritycoffee.com",
    "domain": "puritycoffee.com",
    "myshopifyDomain": "purity-coffee.myshopify.com",
    "shopId": "40613871783",
    "description": "Shop Purity Coffee online today. Explore organic, specialty grade coffee that is purity tested, antioxidant rich and crafted for a cleaner cup at Purity Coffee.",
    "emails": [
        "support@puritycoffee.com"
    ],
    "phones": [
        "844-787-4892"
    ],
    "contactPageUrl": "https://puritycoffee.com/pages/help-center",
    "legalName": "Purity Coffee",
    "address": "Purity Coffee Inc., 1010 East North Street, Suite B3, Greenville SC 29601, United States",
    "vatNumber": null,
    "registrationNumber": null,
    "city": "Greenville",
    "province": "South Carolina",
    "country": "US",
    "currency": "USD",
    "socials": {
        "instagram": "https://www.instagram.com/purity_coffee",
        "facebook": "https://www.facebook.com/mypuritycoffee",
        "tiktok": "https://www.tiktok.com/@puritycoffee",
        "youtube": "https://www.youtube.com/@puritycoffee5260",
        "pinterest": null,
        "x": null,
        "linkedin": null
    },
    "productCount": 103,
    "collectionCount": 40,
    "productsSampled": 103,
    "newestProductAt": "2026-10-09T19:22:22.000Z",
    "priceMin": 11,
    "priceMax": 192,
    "topProductTypes": [
        "Whole Bean Coffee",
        "Single-Serve Coffee",
        "Ground Coffee",
        "Hidden",
        "Coffee"
    ],
    "theme": "Impulse",
    "themeVersion": "7.4.0",
    "apps": [
        "Consentmo",
        "EcoCart",
        "Google Tag Manager",
        "Gorgias",
        "Klaviyo",
        "Okendo",
        "Skio",
        "Superfiliate"
    ],
    "shopPayInstallments": true,
    "shipsToCountries": [
        "CA",
        "US"
    ],
    "websiteRead": true,
    "matchedProducts": [
        {
            "title": "FLOW: Original Medium Roast Whole Bean Coffee",
            "url": "https://puritycoffee.com/products/original-roast-whole-bean-coffee",
            "price": 29,
            "currency": "USD"
        },
        {
            "title": "PROTECT: Light-Medium Roast Whole Bean Coffee",
            "url": "https://puritycoffee.com/products/purity-protect",
            "price": 29,
            "currency": "USD"
        }
    ],
    "foundBy": "organic coffee",
    "scrapedAt": "2026-10-20T06:00:00.000Z"
}
```

#### Store fields

| Field | Meaning |
|---|---|
| `rowType` | `store` for a store lead (the free rows are described below). |
| `name`, `storeUrl`, `domain` | The store and its primary address. |
| `myshopifyDomain`, `shopId` | Its permanent `.myshopify.com` address and Shopify shop id. |
| `description` | The store's own description as set in Shopify (`null` when it has none). |
| `emails` | Public emails from its contact policy, homepage and contact page; the store's own domain first. Apps' and placeholder addresses are removed. |
| `phones` | Phone numbers from its contact policy and `tel:` links. |
| `contactPageUrl` | Its contact page, when it has one. |
| `legalName`, `address`, `vatNumber`, `registrationNumber` | From Shopify's contact-information policy (required for stores selling into the EU), when the store filled it in. |
| `city`, `province`, `country`, `currency` | The business location and currency set in Shopify. |
| `socials` | Instagram, Facebook, TikTok, YouTube, Pinterest, X and LinkedIn profile links (`null` when not linked). |
| `productCount`, `collectionCount` | Published products and collections. |
| `productsSampled`, `newestProductAt`, `priceMin`, `priceMax`, `topProductTypes` | Stats of its newest products (up to 250): is it active, how pricey, what it sells. |
| `theme`, `themeVersion` | Its Shopify theme (`Dawn`, `Impulse`, `Prestige`…). |
| `apps` | Apps and pixels its homepage loads (Klaviyo, Judge.me, Recharge, Gorgias, Meta Pixel, Google Tag Manager…). |
| `shopPayInstallments`, `shipsToCountries` | Whether it offers Shop Pay Installments, and the countries it ships to. |
| `websiteRead` | `false` when the store's domain refused our visit (bot protection): contacts then come from its policy only. |
| `matchedProducts` | Up to 3 of its products that matched your search, with price. |
| `foundBy` | The search term that found it, or `domain list`. |
| `scrapedAt` | When the run read it (UTC, ISO 8601). |

#### Free rows

- **`rowType: "skipped"`** — a domain (or found store) not delivered, with `reason`: `notShopify`, `closed`,
  `passwordProtected` or `blocked` (the site refused us; its `.myshopify.com` address often works) and a message.
- **`rowType: "search"`** — per search term: products scanned and available on Shop, stores found, how many were
  delivered, found by an earlier term, delivered in earlier runs, based in another country, or without an email.

Use the dataset views **Store leads**, **Contacts and company**, **Skipped domains** and **Searches** to see each kind.

### Pricing

**US$0.003 per store lead** (US$3 per 1,000 stores), nothing else: no start fee. Skipped domains, stores without an
email (with "Only stores with an email" on), stores based elsewhere and search summaries are free. Set a maximum cost
per run and the Actor stops before reading a store it could not charge for.

### Limits

- Shop returns at most ~500 products per search term, so one term gives roughly 100–150 stores; use several terms
  (`coffee beans`, `espresso`, `cold brew`…) for more.
- Contacts are what stores publish: about 8 in 10 publish an email somewhere; phone numbers and addresses are rarer.
  Emails are not verified for delivery.
- A store behind bot protection on its own domain is still delivered from Shopify's side (location, policy contacts,
  catalog), with `websiteRead: false` and no socials, theme or apps.
- Stores are found through products listed on Shop; a store that does not list its products there is not found by
  search (give its domain instead).

### Is it legal?

This Actor reads only public pages: Shop's catalog through the anonymous agent endpoint Shopify documents, and the pages
every Shopify storefront serves to any visitor, at a gentle pace (one request at a time per site). It never signs in,
never touches carts or checkout, and never bypasses any protection. Emails and phones are the business contacts stores
publish. You are responsible for how you use them: follow the anti-spam and privacy rules that apply to you (CAN-SPAM,
GDPR, CASL). This Actor is **not affiliated with, endorsed or sponsored by Shopify**. Read more in Apify's blog post
on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### Feedback

Need a field or a filter that isn't here? Open an issue in the **Issues** tab — they are answered quickly.

# Actor input Schema

## `searchTerms` (type: `array`):

Product keywords to find Shopify stores by, e.g. <code>organic coffee</code>, <code>yoga mat</code>, <code>dog collar</code>. Each term searches Shopify's Shop catalog and reaches up to ~500 products (Shop's own limit), which is usually 100–150 different stores. Add more terms for more stores; a store found by several terms is delivered once.

## `domains` (type: `array`):

Shopify stores you already have, as domains or links (<code>puritycoffee.com</code>, <code>https://www.cafebritt.com</code>, or the <code>.myshopify.com</code> address). Each is read the same way as a store found by search. Domains that are not Shopify, closed or password protected get a free row saying so.

## `storeCountry` (type: `string`):

Only stores whose own Shopify address is in this country. Shop is asked for products shipping from it, and every store's registered country is checked; stores based elsewhere are skipped for free. Applies to search terms, not to your domain list.

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

Only products (and so stores) that ship to this country, wherever the store is based. Applies to search terms.

## `maxStores` (type: `integer`):

Most store leads this run delivers (and charges), across all search terms and domains.

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

Deliver only stores that publish at least one email address. Stores without one are skipped and not charged.

## `onlyNewStores` (type: `boolean`):

Skip stores this Actor delivered to you in earlier runs that had this option on, so repeated runs build a list without duplicates. The list of delivered stores is kept in a key-value store of your account named <code>steadyscrape-shopify-store-leads-state</code>.

## Actor input object example

```json
{
  "searchTerms": [
    "organic coffee"
  ],
  "storeCountry": "",
  "shipsTo": "",
  "maxStores": 10,
  "requireEmail": false,
  "onlyNewStores": false
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "organic coffee"
    ],
    "maxStores": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/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 = {
    "searchTerms": ["organic coffee"],
    "maxStores": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/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 '{
  "searchTerms": [
    "organic coffee"
  ],
  "maxStores": 10
}' |
apify call steadyscrape/shopify-store-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/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/XwQX55mIOYgJmkbtX/builds/CfXn2Ud7ww28Dr5GS/openapi.json
