Shopify Email Scraper: Store Contacts, Phones & Socials avatar

Shopify Email Scraper: Store Contacts, Phones & Socials

Pricing

from $2.10 / 1,000 store with emails

Go to Apify Store
Shopify Email Scraper: Store Contacts, Phones & Socials

Shopify Email Scraper: Store Contacts, Phones & Socials

Shopify store contacts lookup by domain: give store URLs, get each store's public emails, phones, address and socials plus Shopify facts (store name, country, currency, myshopify domain, product count). $0.003 per store with an email; stores with nothing found are free.

Pricing

from $2.10 / 1,000 store with emails

Rating

0.0

(0)

Developer

Data Gleaner

Data Gleaner

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Shopify Store Contact Finder: Email, Phone & Socials

Shopify store contacts by domain. It answers "find the contact email for this Shopify store", "Shopify store owner email", "Shopify contact page" and "Shopify store contact finder" for a list of stores you already have. Give it store URLs or domains and get each store's public emails, phone numbers, business address and social profiles, plus its Shopify facts: store name, country, currency, myshopify domain and product count.

You pay $0.003 only for a store where an email was found. A store with nothing found is free. No login, no API key, no browser.

It is a lookup, not a discovery database: you bring the stores (from a lead list, a competitor list, a store-search tool or a CRM) and it fills in how to reach each one.

What it does

For each store, it reads what any visitor can see:

  1. /meta.json, Shopify's public store summary: the store name, country, currency, name.myshopify.com domain, product and collection counts, and the countries it ships to. This also tells whether the site runs on Shopify.
  2. Up to 5 pages, stopping as soon as an email on the store's own domain is found: the home page (header and footer), the contact page the store links to, /pages/contact, /pages/contact-us, /policies/terms-of-service and /policies/privacy-policy. The /policies/contact-information page (trade name, phone, email, physical address) is read when the store links to it.
  3. /products.json (optional, one request) for the newest product's creation date and the latest publish date, a quick sign of whether the store is active.

Most stores take 1 to 3 pages. Sites that are not on Shopify are still checked (home page, /contact, /contact-us, /about, /privacy-policy) and come back with isShopify: false.

Only the store's own addresses count. Theme placeholders (your@email.com, name@domain.com, youremail@example.com), image file names, no-reply mailboxes and addresses of Shopify, its apps, payment and shipping partners (Klaviyo, Judge.me, Gorgias, PayPal and so on) are dropped. Addresses on other businesses' domains, such as a parent company, are kept apart in otherEmails and are never billed. The best mailbox for outreach is picked as primaryEmail: the store's own domain first, then general mailboxes (hello@, info@, support@) before legal or privacy desks.

Use cases

  • Lead lists for agencies, apps and suppliers selling to Shopify merchants: turn a list of store domains into emails, phones and socials, and pay only for the stores you can actually reach.
  • Enriching a store-search or competitor export that has domains but no contacts.
  • Qualifying stores by country, currency, catalog size and how recently they added a product.
  • AI agents that need "the contact email of this Shopify store" for one or many domains, with a price per hit and an output that is the same every time.
  • Finding a brand's Instagram, TikTok, Facebook, X, YouTube, Pinterest and LinkedIn from its store.

Input

FieldMeaning
storeUrlsStores to look up: a domain (brooklinen.com), any URL on the store, or name.myshopify.com. Duplicates are removed.
datasetIdOptional. A dataset of another Actor's run; its store sites are added to storeUrls. See below.
datasetField, maxDatasetItemsField to read first (default tries website, storeUrl, shopUrl, myshopifyDomain, domain, url...) and a cap on sites (default 1000).
maxPagesPerStoreMost HTML pages per store, home page included (default 5, max 10). Reading stops at the first own email.
includeProductStatsRead /products.json once for product dates (default true).
onlyWithEmailOutput only stores with an email (default false). Stores without one are free either way.
pagePathsYour own order of pages to check after the home page, e.g. ["/pages/about", "/policies/terms-of-service"].
maxConcurrencyStores processed at once (default 5).
delaySecsPause between requests to the same store (default 1 second, randomised).
requestTimeoutSecs, respectRobotsTxt, proxyConfigurationNetwork options. No proxy by default.

Leave everything empty to run 3 example stores (beardbrand.com, tentree.com, drinkolipop.com; about 10 seconds, 3 x $0.003 = $0.009).

{
"storeUrls": ["brooklinen.com", "https://www.allbirds.com", "beardbrand.myshopify.com"],
"maxPagesPerStore": 5,
"includeProductStats": true,
"onlyWithEmail": false
}

Run it after Google Maps Scraper or any store list

Open the source Actor's Integrations tab, add this Actor (datagleaner/shopify-store-contacts) and set its input to:

{"datasetId": "{{resource.defaultDatasetId}}"}

Every time the source run succeeds, this Actor reads the store sites from its results (website, storeUrl, shopUrl, myshopifyDomain, domain, url and similar, the first usable one), skips items with no site, map or social links, and duplicates, and looks up each store (at most maxDatasetItems, default 1000). Sites that are not on Shopify come back with isShopify: false. Any site, Shopify or not, is billed only when a public email is found, so a Google Maps list costs $0.003 per business with an email and nothing for the rest. Works with Google Maps Scraper results and other store-list Actors. From code:

run = client.actor("datagleaner/shopify-store-contacts").call(run_input={"datasetId": "SOURCE_DATASET_ID"})

The status message tells how many sites were read, how many items had none, and whether the dataset could not be read.

It also works as an integration without setting any input: in the source Actor's Integrations tab choose Add integration and pick this Actor, and the dataset is passed automatically.

Output

One row per store. Fields that were not found are empty or null, never invented. A real row:

{
"domain": "brooklinen.com",
"storeUrl": "https://www.brooklinen.com",
"isShopify": true,
"storeName": "Brooklinen",
"myshopifyDomain": "brooklinen2.myshopify.com",
"country": "US",
"currency": "USD",
"description": "Discover Brooklinen's premium bedding collection. Shop soft sheets, cozy comforters, and s...",
"primaryEmail": "hello@brooklinen.com",
"emails": [
{"email": "hello@brooklinen.com", "source": "contact-page", "foundOn": "https://www.brooklinen.com/pages/contact"},
{"email": "press@brooklinen.com", "source": "contact-page", "foundOn": "https://www.brooklinen.com/pages/contact"},
{"email": "influencer@brooklinen.com", "source": "contact-page", "foundOn": "https://www.brooklinen.com/pages/contact"},
{"email": "sales@brooklinenbusiness.com", "source": "contact-page", "foundOn": "https://www.brooklinen.com/pages/contact"}
],
"otherEmails": [],
"phones": [{"phone": "+16467987447", "raw": "6467987447", "source": "contact-page"}],
"primaryPhone": "+16467987447",
"address": {"formatted": "Brooklyn, New York, US", "street": null, "city": "Brooklyn", "region": "New York",
"postalCode": null, "country": "US", "source": "shopify-meta"},
"socials": {
"instagram": "https://www.instagram.com/brooklinen",
"facebook": "https://www.facebook.com/Brooklinen",
"tiktok": "https://www.tiktok.com/@brooklinen",
"x": "https://x.com/brooklinen",
"youtube": "https://www.youtube.com/c/Brooklinen",
"pinterest": "https://www.pinterest.com/brooklinen",
"linkedin": null
},
"productCount": 523,
"collectionCount": 787,
"newestProductAt": "2026-10-08T19:25:58+00:00",
"lastPublishedAt": "2026-10-08T21:24:05+00:00",
"shipsToCountries": ["AU", "BE", "CA"],
"hasEmail": true,
"pagesFetched": 2,
"pageUrls": ["https://www.brooklinen.com/", "https://www.brooklinen.com/pages/contact"],
"status": "ok",
"error": null,
"input": "brooklinen.com",
"scrapedAt": "2026-10-09T14:39:27+00:00"
}
  • emails[].source is the kind of page: homepage, contact-page, contact-information, terms-of-service, privacy-policy, policy or page. foundOn is the exact URL.
  • address.source is contact-information (the store's legal contact page, full street address), homepage or another page (structured data), or shopify-meta (city, region and country from Shopify's store summary).
  • phones are E.164. On the home page only the header and footer are read for phone numbers, so prices and SKUs are not mistaken for one.
  • status is ok, passwordProtected, unreachable, rateLimited (the store kept answering HTTP 429), invalidUrl or error. Rows that are not ok are free unless an email was still found.

The dataset has two views: Store contacts (one row per store, socials flattened into columns, ready for CSV or Sheets) and All emails (one row per email, with the page it was on).

Pricing

Pay per answer, one event:

  • store-with-email: $0.003 for each store where at least one public email of the store's own was found.
  • A store with nothing found is free. It is still returned with its Shopify facts, phones and socials.
  • Unreachable, rate-limited, invalid and password-protected stores are free.

Worked example. You look up 1,000 Shopify stores. About 85% show a public email, so 850 x $0.003 = $2.55. The other 150 cost nothing. Turn on onlyWithEmail to leave them out of the dataset; the price is the same.

Other Shopify lead tools charge per row whether or not an email is found (around $0.004 to $0.006 a store on the most used ones), or per contact reveal (up to $0.075 each, 25 times this price). Set a maximum total charge on the run and the Actor stops cleanly when it is reached.

What to expect

On a test run of 20 well-known stores, 18 returned an email on the store's own domain (90%), 12 a phone number, 17 an address, and every one at least one social profile, using about 4.7 requests per store. Coverage on small stores depends on what the owner published; a store that hides its email behind a contact form has none to find.

Limits

  • Public pages only. It never submits contact forms, logs in, or asks a store for anything.
  • Headless storefronts (custom front ends on Shopify, such as Hydrogen) may not serve /meta.json, /products.json or the standard /pages/ paths, so they return fewer fields. They are still flagged isShopify: true when Shopify's headers show.
  • productCount is Shopify's published-product count. When /meta.json is missing, it falls back to the number listed on the first /products.json page, which stops at 250.
  • newestProductAt and lastPublishedAt come from the first /products.json page (up to 250 products), so on very large catalogs they are the newest among those.
  • Shopify rate-limits heavy traffic from one IP (HTTP 429) across all its stores at once. The Actor waits and retries with backoff, one 429 slows every worker, and stores still rate-limited get one more try at the end of the run. Any store that stays rate-limited comes back with status: "rateLimited" and is free. On large runs lower maxConcurrency, raise delaySecs, or set proxyConfiguration.
  • Shopify's default robots.txt asks search engines not to index /policies/ on every store. This Actor reads those pages one at a time, the way a visitor would, unless you turn on respectRobotsTxt, which skips them and finds fewer emails.

Use it from n8n, Make, Zapier or an AI agent

Actor ID: datagleaner/shopify-store-contacts

Minimal input:

{"storeUrls": ["beardbrand.com", "brooklinen.com"], "onlyWithEmail": true}

Each tool below runs this Actor with your own Apify API token.

  • n8n: add the Apify node (@apify/n8n-nodes-apify). On n8n Cloud you install it from the community node registry. Choose Run an Actor and get dataset, set Actor to datagleaner/shopify-store-contacts and paste the input above.

  • Make: use the Apify app's Run an Actor module, then Get Dataset Items to read the results. Watch Actor Runs can trigger a scenario when a run finishes.

  • Zapier: use the Apify action Run Actor, then the search Fetch dataset items. The trigger Finished Actor run starts a Zap when a run ends.

  • AI agents (MCP): connect to https://mcp.apify.com/?tools=datagleaner/shopify-store-contacts. Without a token, an agent can still find Actors with the search-actors tool, but running this one needs your Apify account. In Claude Code:

      claude mcp add --transport http apify "https://mcp.apify.com/?tools=datagleaner/shopify-store-contacts"
    

    Then run /mcp to sign in to Apify in your browser. Then ask in plain language, for example: "Find the contact email and Instagram for brooklinen.com and allbirds.com, and say which of these 50 Shopify stores sell in EUR and how to reach them."

  • LangChain (Python):

# pip install langchain-apify, then set APIFY_TOKEN in your environment
import json
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("datagleaner/shopify-store-contacts")
result = tool.invoke({"run_input": json.loads('{"storeUrls": ["beardbrand.com", "brooklinen.com"], "onlyWithEmail": true}')})

FAQ

Does it find stores for me? No. It is a per-domain lookup. Bring the store domains; it returns how to reach each one.

Does it work on stores that are not on Shopify? Yes. They are checked the same way on generic contact paths and come back with isShopify: false and no Shopify facts.

Is the email the owner's personal address? It is whatever the store publishes: usually a support or hello mailbox, sometimes the founder's address on small stores. Nothing hidden is revealed.

Why is an email in otherEmails and not billed? It sits on another business's domain (a parent company, an agency, a 3PL). It may still be useful, but it is not the store's own address, so it does not count as a hit.

Can I pass name.myshopify.com? Yes. The Actor reads the store's primary domain from Shopify and continues there.

What happens with an empty input? It runs 3 example stores and says so in the run's status message.

Responsible use

This Actor reads public pages only. Email addresses and phone numbers can be personal data, especially for small stores run by one person. You are responsible for using the results lawfully, including consent and opt-out rules for outreach (GDPR, CAN-SPAM, CASL and local law), and for respecting the terms of the platforms you use them on.