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

Enrich a list of Shopify stores into B2B leads: business email (incl. Cloudflare-hidden), phone, address, Instagram/Facebook/TikTok, the review apps they run (Judge.me, Loox, Yotpo, Okendo) and product ratings. Confirms each site is Shopify. Pure HTTP, no login, no API key.

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

## Pricing

from $3.00 / 1,000 results

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 Scraper — Emails, Phones & Ratings

Turn a list of **Shopify stores** into outreach-ready **B2B leads**. Give the actor a batch of store URLs (or bare domains) and it returns a clean, structured contact profile for each one:

- 📧 **Emails** — the store's real business email(s), including addresses hidden behind Cloudflare obfuscation
- ☎️ **Phone numbers** — customer-service / business phone where published
- 📍 **Postal address** — pulled from the store's legal/policy pages when present
- 📱 **Social profiles** — Instagram, Facebook, TikTok, YouTube, Pinterest, LinkedIn, X/Twitter
- ⭐ **Ratings** — product aggregate star rating where the store publishes it
- 🧩 **Review / UGC apps** — which platform the store runs (Judge.me, Loox, Yotpo, Okendo, Stamped, Fera, Junip …)
- 🏷️ **Store identity** — name, currency, country, city/region, plus a product sample — and a hard confirmation that the site really is Shopify

No login. No API key. No browser. Just paste your list and run.

***

### Who this is for

This is a **lead-generation and prospecting** tool built around the Shopify ecosystem. It's for anyone who sells **to** Shopify merchants or needs their contact details at scale:

- **Shopify app & theme developers** — build targeted outreach lists of stores that already run a competing app (or *don't* run one yet)
- **Agencies & freelancers** (design, CRO, email, ads, SEO) — find merchants to pitch, with their email and socials ready to go
- **B2B SaaS & service providers** — 3PL, fulfillment, photography, influencer platforms, financing, insurance
- **Dropshipping & wholesale** — research suppliers and competitor storefronts, currency and catalog included
- **Sales & growth teams** — enrich a raw domain list into a CRM-ready contact sheet
- **Market researchers** — map a niche: who uses which review app, which country, which currency

> **You bring the store list.** Export it from BuiltWith / Wappalyzer / myip.ms, a competitor roundup, a Google Sheet, an ad-library scrape, or your own prospecting — then let this actor enrich every domain into a full lead row.

***

### What you get per store

| Field | Description |
|---|---|
| `store` | Clean domain (e.g. `allbirds.com`) |
| `url` | Normalised store origin |
| `isShopify` | `true` only when the site is confirmed Shopify (via `/meta.json` or `/products.json`) |
| `name` | Store name |
| `currency` | Store currency (USD, CAD, GBP, EUR …) |
| `country`, `city`, `province` | Store location from its own metadata |
| `primaryEmail` | Best outreach mailbox (prefers `info@`/`hello@` over `legal@`/`privacy@`) |
| `emails` | All business emails found (incl. Cloudflare-decoded) |
| `primaryPhone` | Best phone number |
| `phones` | All phone numbers found |
| `address` | Postal address from the policy pages, when present |
| `socials` | All social profile URLs |
| `instagram`, `facebook`, `tiktok` | Direct links to the main social handles |
| `reviewApps` | Review/UGC apps detected on the store |
| `hasReviewApp` | Quick boolean flag |
| `rating` | Aggregate product star rating where published |
| `ratingCount` | Number of reviews behind that rating |
| `productSample` | How many products were visible in the catalog sample |
| `sampleProducts` | A few product titles, so you know what the store sells |
| `scrapedAt` | ISO timestamp |

***

### Input

| Field | Type | Description |
|---|---|---|
| `storeUrls` | array | **Required.** Shopify store URLs or bare domains, one per line. `allbirds.com`, `https://mystore.com`, `www.shop.co` all work. |
| `maxProductsToScan` | integer | How many products to open per store when hunting for a published rating. `0` = skip products (fastest). Default `4`. |
| `checkRatings` | boolean | Collect product ratings. Turn off for a pure contact list. Default `true`. |
| `includeNonShopify` | boolean | Keep non-Shopify inputs in the output (with `isShopify = false`) instead of skipping them. Default `false`. |
| `maxConcurrency` | integer | How many stores to process in parallel. Default `6`. |
| `proxyConfiguration` | object | Proxy settings. Apify Proxy (default) is recommended. |

#### Example input

```json
{
  "storeUrls": [
    "deathwishcoffee.com",
    "allbirds.com",
    "pinklily.com",
    "https://drinkolipop.com"
  ],
  "maxProductsToScan": 4,
  "checkRatings": true,
  "maxConcurrency": 6,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

***

### Example output

```json
{
  "store": "pinklily.com",
  "url": "https://pinklily.com",
  "isShopify": true,
  "name": "Pink Lily",
  "currency": "USD",
  "country": "US",
  "city": "Bowling Green",
  "province": "Kentucky",
  "primaryEmail": "info@pinklily.com",
  "emails": ["info@pinklily.com", "privacy@pinklily.com"],
  "primaryPhone": "270-495-3636",
  "phones": ["270-495-3636"],
  "address": "472 Century Street, Bowling Green, KY 42101",
  "socials": [
    "https://instagram.com/pinklilyboutique",
    "https://facebook.com/pinklilyboutique",
    "https://tiktok.com/@pinklily"
  ],
  "instagram": "https://instagram.com/pinklilyboutique",
  "facebook": "https://facebook.com/pinklilyboutique",
  "tiktok": "https://tiktok.com/@pinklily",
  "reviewApps": ["Yotpo", "Fera"],
  "hasReviewApp": true,
  "rating": 4.8,
  "ratingCount": 231,
  "productSample": 10,
  "sampleProducts": ["Floral Wrap Dress", "High-Rise Denim"],
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

***

### How it works

For each store the actor fetches only public endpoints and pages:

1. **`/meta.json`** → store name, currency, country, city/region — and a hard confirmation the site is Shopify. If a store blocks `meta.json`, it falls back to **`/products.json`** to confirm Shopify.
2. **Contact & legal pages** — the home page, `/pages/contact`, `/pages/contact-us`, `/pages/about-us` and the `/policies/*` pages (refund, privacy, terms, contact-information) that every Shopify store exposes. These are where merchants publish their real business email, phone and address.
3. **Extraction** — emails (regex + Cloudflare `data-cfemail` decoding), phone numbers (strict formatting to avoid grabbing dates/IDs), postal address, social links, and review-app detection.
4. **`/products.json` + product pages** — a product sample, plus the aggregate star rating from JSON-LD or the review widget (it scans several products and keeps the rating backed by the most reviews, so one stray single-review product doesn't skew the result).

Everything runs over plain HTTP with an automatic, realistic request fingerprint — no headless browser, so it's fast and cheap.

***

### Tips & notes

- **Coverage is honest.** Small and mid-size merchants publish their email, phone and socials far more openly than mega-brands — and those small/mid stores are exactly who most B2B outreach targets. Some very large brands hide contact behind a form or a locked CDN; those rows will still carry identity + socials, but may lack an email.
- **`isShopify` is a real filter.** Headless or re-platformed sites (some big DTC brands run custom/React frontends) will come back `isShopify: false` and are skipped by default — so your lead list stays clean.
- **Emails are ranked for outreach.** `primaryEmail` prefers a human-reachable mailbox (`info@`, `hello@`, `contact@`) over `legal@`/`privacy@`/`no-reply@`.
- **Phone numbers are conservative by design.** The actor only keeps properly formatted numbers and `tel:` links, so you won't get dates, order IDs or tracking numbers masquerading as phones.
- **Ratings are "where available".** Not every store publishes a machine-readable rating; when none is found, `rating` is `null` but `reviewApps` still tells you which review platform they use.
- **Verify emails before a big send.** Pair this with an email-verification step to protect your sender reputation.

***

### FAQ

**Do I need a Shopify API key or app?**
No. The actor only reads public endpoints and pages.

**Can it discover stores from a keyword?**
No — it enriches a list you provide. Reliable keyword discovery needs a search/directory source; feeding your own curated list (from BuiltWith, myip.ms, ad libraries, competitor lists, etc.) produces far cleaner, more relevant leads.

**Does it work for non-US stores?**
Yes. Currency and country come straight from each store's own metadata, and socials/emails are language-agnostic. Phone extraction is tuned for North-American formatting plus any `tel:` link, so international phone coverage depends on how the store marks it up.

**How many stores can I run?**
As many as you like — paste thousands of domains. Tune `maxConcurrency` and `maxProductsToScan` to balance speed vs. rating coverage.

**Is this the same as the Shopify catalog scraper?**
No. A catalog scraper pulls products/variants/prices. **This one builds a lead profile** — the merchant's contact details, socials, tech stack and rating — for sales and prospecting.

***

### Related use cases

Shopify store leads · Shopify email scraper · ecommerce lead generation · DTC brand contacts · Shopify app developer prospecting · agency outreach list · Shopify merchant directory · review app detection (Judge.me / Loox / Yotpo / Okendo) · competitor store research · dropshipping supplier research · B2B contact enrichment.

# Actor input Schema

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

List of Shopify stores to turn into leads. Paste full URLs or bare domains (e.g. allbirds.com) — one per line. Bring your own list from a BuiltWith / myip.ms export, a competitor list, a Google Sheet, etc.

## `maxProductsToScan` (type: `integer`):

How many of each store's products to open when looking for a published aggregate rating. 0 = skip products entirely (fastest). More = higher chance of catching a rating.

## `checkRatings` (type: `boolean`):

Look for an aggregate star rating on the store's product pages (JSON-LD / review-widget). Turn off for pure contact-only lead lists.

## `includeNonShopify` (type: `boolean`):

By default, inputs that aren't actually Shopify are skipped. Enable this to keep them in the dataset (with isShopify = false) so you can see what was filtered.

## `maxConcurrency` (type: `integer`):

How many stores to process in parallel.

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

Proxy settings. Apify Proxy (default) is recommended so requests are distributed across IPs.

## Actor input object example

```json
{
  "storeUrls": [
    "mystore.com",
    "https://another-store.com"
  ],
  "maxProductsToScan": 4,
  "checkRatings": true,
  "includeNonShopify": false,
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `leads` (type: `string`):

Shopify store lead profiles — contact details, socials, review apps and ratings.

# 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": [
        "deathwishcoffee.com",
        "allbirds.com",
        "pinklily.com",
        "drinkolipop.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/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 = {
    "storeUrls": [
        "deathwishcoffee.com",
        "allbirds.com",
        "pinklily.com",
        "drinkolipop.com",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/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 '{
  "storeUrls": [
    "deathwishcoffee.com",
    "allbirds.com",
    "pinklily.com",
    "drinkolipop.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/shopify-store-leads-scraper --silent --output-dataset

```

## MCP server setup

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