# Shopify Email Scraper - Bulk Export to CSV, JSON, API (`reapx/shopify-email-scraper`) Actor

Extract merchant contact details from Shopify stores: store email, store and product name, domain, product title, vendor, tags, price, variants and availability. Build a contactable merchant list and export it to CSV, Excel, JSON or the API.

- **URL**: https://apify.com/reapx/shopify-email-scraper.md
- **Developed by:** [Tarek Etman](https://apify.com/reapx) (community)
- **Categories:** Lead generation, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.60 / 1,000 emails

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/platform/actors/running/actors-in-store#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 Email Scraper

Shopify Email Scraper extracts structured records in bulk and exports them for analysis, enrichment
and downstream pipelines. It covers contact, details, web-crawling, discovers, information, social, media, handles, websites, link-in-bio, pages, crawls, linked, sites, detects, collects, emails, phone, numbers, messaging-platform.

Built for teams that need identifiers, whatsapp, telegram, discord, snapchat, profile, urls, linkedin without maintaining scrapers, proxies or browser
infrastructure themselves.

### Quick start (SDK examples)

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("shopify-email-scraper").call(run_input={"targets": ["<target>"], "maxResults": 100})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### JavaScript

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

const client = new ApifyClient({ token: "YOUR_APIFY_TOKEN" });
const run = await client.actor("shopify-email-scraper").call({ targets: ["<target>"], maxResults: 100 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### cURL

```curl
curl -X POST "https://api.apify.com/v2/acts/shopify-email-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"targets":["<target>"],"maxResults":100}'
```

### Fields returned

| field | description | type |
|---|---|---|
| `email` | email returned for every record | string |
| `name` | name returned for every record | string |
| `url` | url returned for every record | string |
| `domain` | domain returned for every record | string |
| `title` | title returned for every record | string |
| `available` | available returned for every record | string |
| `id` | id returned for every record | string |
| `vendor` | vendor returned for every record | string |
| `tags` | tags returned for every record | string |
| `price` | price returned for every record | string |
| `variants` | variants returned for every record | string |
| `handle` | handle returned for every record | string |
| `description` | description returned for every record | string |
| `scrapedAt` | scrapedAt returned for every record | string |

### What it does

- Extract contact, details, web-crawling, discovers, information, social into structured rows.
- Enrich each record with media, handles, websites, link-in-bio, pages, crawls.
- Bulk export covering linked, sites, detects, collects, emails, phone.
- Pipeline integration for numbers, messaging-platform, identifiers, whatsapp, telegram, discord.
- Downstream analysis across snapchat, profile, urls, linkedin, twitter, instagram.
- Recurring monitoring of facebook, youtube, tiktok, pinterest, threads, reddit.
- Deduplicated output keyed on the record identifier.
- Configurable result caps and runtime bounds.

### Use cases

- **Lead generation** — build contactable lists covering contact, details, web-crawling, discovers, information
- **Data enrichment** — attach social, media, handles, websites, link-in-bio to an existing record set
- **Market research** — map pages, crawls, linked, sites, detects across a category or region
- **Competitive monitoring** — track collects, emails, phone, numbers, messaging-platform over time on a schedule
- **AI and RAG pipelines** — feed clean structured rows into embeddings and retrieval
- **Warehousing** — land identifiers, whatsapp, telegram, discord, snapchat into BigQuery, Snowflake or Postgres

### Input

Provide `targets` as a list of URLs or identifiers, one per line.

| input | purpose |
|---|---|
| `targets` | URLs or identifiers to process, one per line |
| `maxResults` | hard cap on returned rows |
| `maxSeconds` | runtime bound for the run |
| `includeEmpty` | return rows that resolved to no data, or skip them |

### Output

Every run writes a dataset exportable as CSV, Excel, JSON, or readable directly from the Apify API. Attach a webhook to push results into your own system as soon as a run finishes.

### Integrations

Works with Zapier, Make, n8n, Google Sheets, Slack, and any HTTP endpoint via webhooks. The Apify MCP server exposes this Actor to AI agents directly.

### Performance and limits

Runs are concurrent and bounded by `maxResults` and `maxSeconds`. Proxy rotation and retry handling are managed for you. Failed targets are reported rather than silently dropped.

### Frequently asked questions

##### Do I need an account or cookies?

No. The Actor reads public data only and requires no login, cookies or personal API keys.

##### What formats can I export?

CSV, Excel, JSON, or read the dataset straight from the Apify API.

##### What does a row contain?

Every row carries contact, details, web-crawling, discovers, information, social, media, handles where available.

##### Can I schedule it?

Yes. Attach a schedule or a webhook and the dataset is produced on your cadence.

##### How do I limit cost?

Use `maxResults` to cap returned rows and `maxSeconds` to bound runtime.

##### Is the output stable?

Field names are fixed by the dataset schema, so downstream pipelines do not break between runs.

### Field glossary

**`email`** — the email associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`name`** — the name associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`url`** — the url associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`domain`** — the domain associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`title`** — the title associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`available`** — the available associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`id`** — the id associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`vendor`** — the vendor associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`tags`** — the tags associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`price`** — the price associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`variants`** — the variants associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`handle`** — the handle associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`description`** — the description associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.
**`scrapedAt`** — the scrapedAt associated with the record. Present on every row where the source exposes it; absent values are returned as null rather than omitted, so column order stays stable across runs and downstream schemas do not drift.

### Troubleshooting

- **Empty dataset** — Check that `targets` contains reachable identifiers and that `includeEmpty` is set the way you expect.
- **Run times out** — Lower `maxResults` or raise `maxSeconds`; very large target lists are better split across scheduled runs.
- **Missing fields** — Not every source exposes every field. Absent values are returned as null so the schema stays stable.
- **Rate limiting** — Proxy rotation is automatic. If a source throttles hard, reduce concurrency and retry.
- **Duplicate rows** — Output is deduplicated on the record identifier; duplicates across separate runs are expected by design.

### Data quality notes

Records are parsed from public sources covering contact, details, web-crawling, discovers, information, social, media, handles, websites, link-in-bio. Values are returned exactly as published rather than normalised or inferred, so you can audit any row back to its source URL. Timestamps are ISO-8601 UTC. Numeric counters are integers. No field is synthesised when the source does not publish it.

### Scheduling and automation

Attach a schedule to run this Actor hourly, daily or weekly. Combine it with a webhook to push each finished dataset into your warehouse, CRM or Slack channel automatically. Runs are idempotent with respect to their input, so a repeated schedule produces a comparable dataset rather than a drifting one.

### Support

Open an issue on the Actor's Issues tab. Include the run ID and the input used so it can be reproduced.

# Actor input Schema

## `targets` (type: `array`):

URLs, handles or search terms — any mix. Each one is resolved to the cheapest route that returns data. Provide `targets` as a list, one per line (for example `example-value`). This is the work list the run iterates over.

## `maxResults` (type: `integer`):

Stop after this many rows. You are charged per row returned. Provide `maxResults` as a whole number between 1 and 100000 (for example `100`). Use it to bound both runtime and spend on open-ended inputs.

## `maxSeconds` (type: `integer`):

Stop cleanly after this long and keep the rows already found. Provide `maxSeconds` as a whole number between 30 and 3600 (for example `100`). Use it to stop a run before it exceeds your time budget.

## `includeEmpty` (type: `boolean`):

Adds an unbilled row for each target with no data. Never charged. Toggle `includeEmpty` on or off. Turn it on when you need a row for every input, even empty ones.

## Actor input object example

```json
{
  "targets": [
    "allbirds.com"
  ],
  "maxResults": 100,
  "maxSeconds": 240,
  "includeEmpty": false
}
```

# Actor output Schema

## `dataset` (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 = {
    "targets": [
        "allbirds.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("reapx/shopify-email-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 = { "targets": ["allbirds.com"] }

# Run the Actor and wait for it to finish
run = client.actor("reapx/shopify-email-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 '{
  "targets": [
    "allbirds.com"
  ]
}' |
apify call reapx/shopify-email-scraper --silent --output-dataset

```

## MCP server setup

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