# Mi Email Scraper (`email_scraper/mi-email-scraper`) Actor

Mi Email Scraper gathers public contact emails linked to Xiaomi (Mi) community and partner pages by keyword, supporting consumer electronics outreach and leads.

- **URL**: https://apify.com/email_scraper/mi-email-scraper.md
- **Developed by:** [Email Scraper](https://apify.com/email_scraper) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

### 🔍 Mi Email Scraper – Overview

The Mi Email Scraper is an Apify Actor that extracts public email addresses from Mi. Give the Mi Email Scraper some keywords and, if you like, a location, and it returns a tidy dataset of Mi contact data: the email address, the page it came from, a short description and the search that found it. It is built for B2B prospecting and outreach.

Mi is the Xiaomi (Mi) consumer electronics brand. The Mi Email Scraper is built for anyone who wants to contact distributors and retailers without searching page by page, from B2B prospecting to recruiting. You stay in control with keyword, location, domain and limit settings, and you download the Mi email list in the format you prefer. ✅

> ✨ **Mi Email Scraper at a glance**
>
> - **Platform:** Mi (mi.com)
> - **What you get:** public email addresses of distributors and retailers
> - **How you search:** keywords, locations and email domains
> - **Data:** email, page title, description, link and lead details
> - **Best for:** B2B lead generation, prospecting and outreach
> - **Export:** JSON, CSV, Excel or the Apify API

Whether you run the Mi Email Scraper once for a quick list or on a schedule for ongoing Mi lead generation, the settings stay the same, so results from different runs are easy to compare.

***

### ⭐ Mi Email Scraper – Key Features

The Mi Email Scraper is built for fast, repeatable Mi lead generation:

- **All-in-one email finder** – the Mi Email Scraper locates Mi pages for your keywords and extracts the email addresses shown there, so the Mi Email Scraper is both an email finder and an email extractor for Mi.
- **Mi keyword search** – run several keywords in one go, such as "distributor" and "retailer", and collect contact data for each.
- **Location targeting** – narrow results to a country, state or city, or add a list of extra locations that are each searched on their own.
- **Email domain control** – look for @gmail.com, @yahoo.com, @outlook.com or your own suffixes, accept any address, or keep business emails only.
- **Must-include and exclude words** – keep only results that mention the words you need and skip snippets with words you do not want.
- **Limits that protect your budget** – cap the emails per search combination and set one total limit for the whole run.
- **Parallel searches** – the Mi Email Scraper can run up to 10 Mi searches at the same time to finish long keyword lists sooner.
- **Duplicate-free results** – an email found by several searches is saved only once, so your email list stays clean.
- **Do-not-contact list** – keep opted-out addresses and existing contacts out of your dataset.
- **Lead history** – skip emails you already collected in earlier runs, so you only get new leads.
- **Optional extras** – add phone numbers shown in the result text and check email domains before saving.
- **Resumable runs** – an interrupted Mi Email Scraper run continues from its saved progress instead of starting over.
- **Only Mi results** – results from other websites are dropped, so every row links to a page on Mi.
- **Ready for your tools** – send leads to a CRM, spreadsheet or automation through Apify integrations and webhooks.

***

### 📊 Mi Email Scraper – What Data You Can Extract

The Mi Email Scraper saves one row of Mi contact data for every unique email address:

| Field | What it contains |
| --- | --- |
| `network` | Source label, `Mi.com` |
| `keyword` | The keyword that produced the result |
| `title` | Title of the result |
| `description` | Result text in which the email appeared |
| `url` | Link to the page |
| `email` | The email address |
| `location` | Location used for the search, or null |
| `emailType` | `free` for webmail providers, `business` for other domains |
| `username` | Handle or first path segment of the Mi link, when it can be read |
| `followersCount` | Follower count if the result text shows one, otherwise null |
| `influencerTier` | Under 1K, Nano, Micro, Macro or Mega, from the follower count; null if unknown |
| `emailStatus` | Only with email verification: `valid` or `unverified` |
| `phoneNumbers` | Only with phone extraction: numbers found in the result text |

> 💡 **Good to know:** the Mi Email Scraper reads the public text shown for each Mi result. Only email addresses that are visible there can be found, so results depend on what Mi users publish.

***

### 🚀 Mi Email Scraper – How to Use It

Getting your first Mi email list with the Mi Email Scraper takes only a few minutes:

- **Step 1 – Open the Actor:** open the Mi Email Scraper in Apify Store and click Start.
- **Step 2 – Add keywords:** enter one or more Mi search terms, for example "distributor".
- **Step 3 – Set a location (optional):** type a country or city such as Beijing, or leave the field empty.
- **Step 4 – Choose email types:** keep @gmail.com or add other suffixes, or switch the email mode to any address or business emails only.
- **Step 5 – Set limits:** decide how many emails each combination may collect and, if you like, a total for the run.
- **Step 6 – Run and export:** start the Mi Email Scraper, follow the dataset as it fills, then download JSON, CSV or Excel.

***

### 🎯 How to Extract Mi Emails by Keyword and Location

Every Mi keyword is combined with every location and every email suffix, and each combination is its own search with its own email target. Two keywords, three locations and two suffixes make 12 searches. With the Mi Email Scraper, use the total limit to keep large Mi runs predictable, and use the extra locations list to cover many cities, for example Beijing, in a single run. A search for "distributor" in Beijing is one combination, and "retailer" in Beijing is another.

***

### 🧭 Can You Filter Mi Email Scraper Results by Email Domain?

Yes. The email mode setting of the Mi Email Scraper has three options:

- **Only the domains listed** – the default; finds exactly the suffixes you enter, such as @gmail.com.
- **Any email address** – accepts every address found in Mi result text, whatever the domain.
- **Business emails only** – accepts any address except free webmail providers like Gmail, Yahoo or Outlook, which suits B2B outreach on Mi.

The two broad modes find addresses a fixed list would miss, but expect fewer results per search and some noise.

***

### 💼 Mi Email Scraper – Use Cases

Teams use the Mi Email Scraper for:

- **Consumer electronics channel outreach** – a ready email list of distributors and retailers that you can contact right away.
- **Distributor prospecting** – search "distributor" in Beijing or any other place and compare the Mi results by location.
- **Retail lead lists** – export the contact data to your CRM, spreadsheet or B2B outreach tool.
- **Market research** – schedule the Mi Email Scraper to keep your Mi lead generation running.

Because the Mi Email Scraper returns structured data, it fits manual research as well as automated lead generation and outreach pipelines.

***

### ⚙️ Mi Email Scraper – Input

The Mi Email Scraper accepts the fields below. Only `keywords` is required; every other field has a default.

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `keywords` | list | `["distributor", "retailer"]` | Keywords to look for, one per line. Each keyword runs on its own. |
| `location` | text | empty | Optional country, state or city added to every search. |
| `locations` | list | `[]` | Extra places, each searched separately with the same keywords. |
| `emailSearchMode` | text | `domainList` | Which emails to look for: your domain list, any address, or business emails only. |
| `customDomains` | list | `["@gmail.com"]` | Email suffixes to look for, such as @gmail.com or @yahoo.com. |
| `maxEmails` | number | `5` | Emails per search combination (keyword + location + domain). Free accounts: 100 at most. |
| `maxTotalEmails` | number | `0` | Hard stop for the whole run. 0 means no total limit. |
| `maxConcurrentSearches` | number | `5` | How many searches run at the same time (1 to 10). |
| `minFollowers` | number | `0` | Keep only results showing at least this many followers. 0 switches it off. Mostly useful on social profiles. |
| `maxFollowers` | number | `0` | Keep only results showing at most this many followers. 0 switches it off. Mostly useful on social profiles. |
| `profilesOnly` | true/false | `false` | Keep only results whose link looks like a single profile page. Mostly useful on social profiles. |
| `includeWords` | list | `[]` | A result is kept only if it contains at least one of these words. |
| `excludeWords` | list | `[]` | Results containing any of these words are skipped. |
| `extractPhoneNumbers` | true/false | `false` | Also return phone numbers written in the result text. |
| `verifyEmails` | true/false | `false` | Check format, placeholders and mail servers before saving an address. |
| `skipPreviouslyFoundEmails` | true/false | `false` | Skip addresses saved by earlier runs under the same history name. |
| `historyStoreName` | text | `mi-email-history` | Name of the saved history (lowercase letters, numbers, hyphens). |
| `excludeEmails` | list | `[]` | Addresses or @domains that must never appear in the results. |

#### 🧪 Example input

```json
{
  "keywords": ["distributor", "retailer"],
  "location": "Beijing",
  "emailSearchMode": "domainList",
  "customDomains": ["@gmail.com", "@yahoo.com"],
  "maxEmails": 20,
  "maxTotalEmails": 100,
  "maxConcurrentSearches": 5,
  "excludeWords": ["spam"]
}
```

***

### 📦 Mi Email Scraper – Output

Results are written to the run's dataset as they are found, so you can watch the list grow. Each item contains the fields described above. A short run summary (unique emails, skipped results by reason, searches finished) is also stored with the run.

#### 🧾 Example output

```json
[
  {
    "network": "Mi.com",
    "keyword": "distributor",
    "title": "Distributor in Beijing | Mi",
    "description": "Example listing for distributor in Beijing. Contact: sample.contact@gmail.com",
    "url": "https://mi.com/sample_distributor",
    "email": "sample.contact@gmail.com",
    "location": "Beijing",
    "emailType": "free",
    "username": "sample_distributor",
    "followersCount": null,
    "influencerTier": null
  },
  {
    "network": "Mi.com",
    "keyword": "retailer",
    "title": "Second example result | Mi",
    "description": "Another example description with sample.team@yahoo.com in the text.",
    "url": "https://mi.com/sample_distributor_2",
    "email": "sample.team@yahoo.com",
    "location": "Beijing",
    "emailType": "free",
    "username": "sample_distributor_2",
    "followersCount": null,
    "influencerTier": null
  }
]
```

The data above is example data that shows the structure of Mi results.

***

### 💰 Mi Email Scraper – Pricing

The Mi Email Scraper uses Apify's pay-per-result model: you pay for the Mi emails that are saved to your dataset. Duplicates, addresses removed by your filters and addresses that fail verification are not saved or charged.

- **Keep costs predictable:** set `maxEmails`, `maxTotalEmails` and the maximum cost of the run.
- **Free Apify plans:** up to 100 emails per search combination.
- **Current rates:** see the pricing information on the Actor page.

***

### ✅ Mi Email Scraper – Tips and Best Practices

Get more from the Mi Email Scraper with these habits:

- **Use several specific keywords** – instead of only one broad term, try close variations such as "distributor" and "retailer".
- **Start small** – run the Mi Email Scraper with a low `maxEmails` first, check the results, then scale up.
- **Loosen the search if results are sparse** – add more email suffixes, more keywords or clear the location.
- **Use include and exclude words** – they keep the email list relevant and remove noise.
- **Raise parallel searches** – 5 to 10 searches at once finish long runs sooner.
- **Use lead history for repeat runs** – switch on skipping of earlier emails so each run returns new leads only and your outreach never repeats.
- **Respect privacy rules** – use the contact data responsibly and follow the laws and platform terms that apply to your outreach.

***

### ❓ Mi Email Scraper – Frequently Asked Questions

#### 💬 What is the Mi Email Scraper?

It is an Apify Actor and email finder that extracts public email addresses from Mi based on your keywords and saves them as structured data, ready for outreach.

#### 💬 Who is the Mi Email Scraper for?

It is for anyone who needs contact data for distributors and retailers: sales teams, recruiters, agencies and researchers. Typical goals are consumer electronics channel outreach and distributor prospecting.

#### 💬 How does the Mi Email Scraper find emails on Mi?

It searches public results for Mi pages with each keyword and reads the email addresses shown in the result title and description. Results from other websites are skipped.

#### 💬 Do I need to log in to Mi to use the Mi Email Scraper?

No. The Mi Email Scraper works without any Mi login or account.

#### 💬 Can I extract Mi emails for a specific city or country?

Yes. Use the location field for one place or the locations list for several, for example Beijing. Each location is searched separately.

#### 💬 What data does the Mi Email Scraper return?

Each row has the email address, the keyword, the page title, description and link, the location, the email type and optional follower, phone and verification fields.

#### 💬 Can the Mi Email Scraper get phone numbers from Mi as well?

Yes, optionally. Switch on phone extraction and the Mi Email Scraper adds the numbers written in the result text to the `phoneNumbers` field.

#### 💬 Why did my Mi run return fewer emails than expected?

The Mi Email Scraper can only find addresses that are publicly shown for Mi results. Try more keywords, more email suffixes, a broader location or the any-address mode.

#### 💬 How do I export Mi emails to CSV or Excel?

Open the run's dataset and choose CSV, Excel or JSON, or fetch the email list through the Apify API.

#### 💬 Is the Mi Email Scraper an email finder or an email extractor?

Both. The Mi Email Scraper finds Mi pages for your keywords and extracts the email addresses shown there, so it works as an email finder and an email extractor for Mi.

***

### 🤝 Support

Questions, ideas or a custom scraper for Mi? The Mi Email Scraper is actively maintained, so get in touch:

- contact me by email : alphascraper69@gmail.com

# Actor input Schema

## `keywords` (type: `array`):

A list of keywords or queries to search for.

## `location` (type: `string`):

Optional country, state or city used to narrow the search. Leave it empty to search without a geographic filter.

## `locations` (type: `array`):

Optional extra countries, states or cities, so one run can cover many places, for example: Miami, Austin, Denver. Every location is searched on its own with the same keywords and domains, in addition to the Region / Location field above if that is filled in. Each keyword + location + domain combination gets its own email limit. The searches multiply: 3 keywords × 5 locations × 2 domains = 30 combinations, so pair a long list with the total email limit below. An email found under more than one location is only saved once.

## `emailSearchMode` (type: `string`):

Controls how email addresses are matched. 'Only the domains listed' searches for exactly the suffixes you enter in the field below (the original behaviour). 'Any email address' accepts every address found in a profile description, whatever the domain. 'Business emails only' accepts any address except those from free webmail providers (Gmail, Yahoo, Outlook, Hotmail, iCloud, AOL, Proton and similar), which is the better choice for B2B outreach. The two broad modes find emails that a fixed domain list would miss, but expect fewer results per search and some noise, so combine them with 'Verify email domains' and consider adding Exclude words.

## `customDomains` (type: `array`):

List of custom email domains. Used when 'Which emails to look for' is set to 'Only the domains listed'; ignored in the 'Any email address' and 'Business emails only' modes.

## `maxEmails` (type: `integer`):

How many addresses each search keyword + domain suffix combination may collect before the finder moves on to the next one. This is a per-combination target, not a run-wide total: with 3 keyword and 2 Domains and a limit of 20, the run works through all 6 combinations and aims for up to 20 addresses in each, so up to 120 overall. Lower values finish sooner and cost less; higher values dig deeper but never guarantee a fuller result, since the run can only find what is publicly listed. In the 'Any email address' and 'Business emails only' modes there is no domain to combine with, so the limit applies per keyword.

## `maxTotalEmails` (type: `integer`):

A hard stop for the entire run, across every keyword and domain combination. Once this many emails have been collected the run finishes cleanly and keeps everything found so far. Use it to keep pay-per-result costs predictable: for example, 20 keywords with a per-combination limit of 50 could otherwise return up to 1,000 emails. Leave at 0 to rely only on the per-combination limit above.

## `maxConcurrentSearches` (type: `integer`):

Every keyword + location + domain combination is its own search, and the searches do not depend on each other, so the Actor can run several at the same time instead of one after another. Most of a search is spent waiting for Google, so 4 searches at a time finish a long list roughly 3 to 4 times sooner, at the same cost per result. Limits, duplicate removal, filters and the total limit work exactly as before: an email found by two searches at once is still saved only once, and the total limit is never exceeded. What changes is the order: rows arrive as searches finish, and an email that several searches find is credited to whichever found it first. Set 1 to run one search at a time in the original order. Higher numbers finish sooner but send more requests at once, which can slow Google's answers down; 10 is the maximum. It makes no difference when there is only one search.

## `minFollowers` (type: `integer`):

Only keep profiles with at least this many followers. Handy for skipping empty or brand-new accounts. When a follower filter is set, results whose follower count Google does not show (and all posts and reels) are skipped, so expect fewer rows than without the filter.

## `maxFollowers` (type: `integer`):

Only keep profiles with at most this many followers. Combine with the minimum to target a range, for example 10,000 to 100,000 for micro-influencers. Profiles for which Google shows no follower count are skipped when this filter is set.

## `profilesOnly` (type: `boolean`):

Most Google results for Mi are not profiles: they are individual posts, reels, explore / tag pages, and they are often job ads or captions rather than a person you can contact. Switch this on to keep only results that point to a profile page (mi.com/username), so every saved row is one account and nothing else is saved or charged. Recommended for influencer and B2B lead lists. It is ticked by default when you start a run in the Console; API calls and saved tasks keep it off unless you set it, so existing setups behave as before.

## `includeWords` (type: `array`):

Words or phrases that must appear in the profile's title or description snippet. A result is kept only if it contains at least one of them, for example: coach, agency, booking, collab. Matching ignores letter case, and single words only match as whole words. Leave empty to keep every result. This is stricter than the search keywords, which Google matches loosely. If a result contains both an include word and an exclude word, it is skipped.

## `excludeWords` (type: `array`):

Words or phrases you do not want to see, for example: crypto, onlyfans. If any of them appears in a profile's description snippet, that whole snippet is skipped and no email address is taken from it. Matching ignores letter case, and single words only match as whole words. Leave empty to keep every snippet.

## `extractPhoneNumbers` (type: `boolean`):

Also pick up phone and WhatsApp numbers that are written in the profile description and return them in a phoneNumbers field next to the email. Off by default because phone numbers are personal data and some number-like text can be misread, so review them before use.

## `verifyEmails` (type: `boolean`):

Checks every address before it is saved: it must be a well-formed address, must not be an obvious placeholder (such as example@gmail.com or yourname@gmail.com), and its domain must have working mail servers (DNS MX lookup). Addresses that fail are dropped, so they are not saved or charged. Saved rows get an emailStatus of 'valid' or 'unverified' (when the DNS lookup could not be completed). This does not confirm that the individual mailbox exists. It is most useful with 'Any email address' and 'Business emails only', where domains vary.

## `skipPreviouslyFoundEmails` (type: `boolean`):

When switched on, the run loads the list of emails saved under the history name below, skips any address already on it, and adds every new address to it. The result is a dataset that contains only new leads. Off by default, so every run starts from scratch.

## `historyStoreName` (type: `string`):

Name of the saved history used by 'Skip emails found in earlier runs'. Use the same name across runs to share one history, or a different name for each campaign to keep campaigns separate. Only lowercase letters, numbers and hyphens, 3–63 characters. The history is kept in a named Apify storage that stays in your account until you delete it.

## `excludeEmails` (type: `array`):

Addresses or whole domains that must never appear in the results, for example people who asked not to be contacted, existing customers, or contacts already in your CRM. Enter full addresses (jane@brand.com) or domains (@brand.com). Matching ignores letter case. A skipped address is not saved and not charged.

## Actor input object example

```json
{
  "keywords": [
    "distributor",
    "retailer"
  ],
  "location": "",
  "locations": [],
  "emailSearchMode": "anyDomain",
  "customDomains": [
    "@gmail.com"
  ],
  "maxEmails": 5,
  "maxTotalEmails": 0,
  "maxConcurrentSearches": 5,
  "minFollowers": 0,
  "maxFollowers": 0,
  "profilesOnly": false,
  "includeWords": [],
  "excludeWords": [],
  "extractPhoneNumbers": false,
  "verifyEmails": false,
  "skipPreviouslyFoundEmails": false,
  "historyStoreName": "mi-email-history",
  "excludeEmails": []
}
```

# 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 = {
    "keywords": [
        "distributor",
        "retailer"
    ],
    "location": "",
    "locations": [],
    "customDomains": [
        "@gmail.com"
    ],
    "profilesOnly": false,
    "includeWords": [],
    "excludeWords": [],
    "excludeEmails": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("email_scraper/mi-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 = {
    "keywords": [
        "distributor",
        "retailer",
    ],
    "location": "",
    "locations": [],
    "customDomains": ["@gmail.com"],
    "profilesOnly": False,
    "includeWords": [],
    "excludeWords": [],
    "excludeEmails": [],
}

# Run the Actor and wait for it to finish
run = client.actor("email_scraper/mi-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 '{
  "keywords": [
    "distributor",
    "retailer"
  ],
  "location": "",
  "locations": [],
  "customDomains": [
    "@gmail.com"
  ],
  "profilesOnly": false,
  "includeWords": [],
  "excludeWords": [],
  "excludeEmails": []
}' |
apify call email_scraper/mi-email-scraper --silent --output-dataset

```

## MCP server setup

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