# Instagram Influencer Search — Hashtag Search, Emails (`afanasenko/instagram-influencer-search`) Actor

Scrape Instagram influencers by hashtag and keyword search — influencer discovery and creator search in any niche. Set a follower range and a minimum engagement rate; every profile returns emails, phone, bio links, business category and Reels views. No login needed.

- **URL**: https://apify.com/afanasenko/instagram-influencer-search.md
- **Developed by:** [Andrey Afanasenko](https://apify.com/afanasenko) (community)
- **Categories:** Lead generation, Social media, Automation
- **Stats:** 24 total users, 16 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 profiles

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/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

## Instagram Influencer Search — Hashtag Search, Emails

[![Apify Actor](https://apify.com/actor-badge?actor=afanasenko/instagram-influencer-search)](https://apify.com/afanasenko/instagram-influencer-search)

> **Give it a niche — a keyword or a hashtag — and get back the Instagram accounts in it, each enriched with email, phone, bio links, follower counts, engagement rate and Reels views. 20+ filters run before you pay attention to a row, so what lands in the dataset is the shortlist, not the raw search.**

Instagram's own search gives you names. This actor gives you the accounts behind them, already qualified: set a follower range, an engagement floor and a language, and only the profiles that match your target persona reach the dataset. No login, no cookies, no Instagram account of yours involved.

### 🎯 What it does

You give the actor search terms — plain keywords, hashtags, or both:

- **Search Queries** are matched against Instagram account names and bios. `fitness coach`, `veterinario`, `marketing agency`. Any language.
- **Search Hashtags** collect the **authors of that hashtag's top posts**. Those accounts skew larger and already-popular, so a follower floor keeps a far higher share of them than plain keyword search does.

Every term is searched in parallel, and the results are merged **round-robin** — one candidate from each term in turn — so a single broad term cannot swallow your whole budget while a narrower one returns nothing.

For every account that comes back you get:

- **Identity** — handle (Account URL), Full Name, Profile Picture, verified flag.
- **Audience** — Followers Count, Following Count, Total Posts, Posts per Month, Last Post age in days.
- **Reels analytics** — Reels Count, Last Reel age, Median Views, Views/Followers ratio.
- **Engagement** — Avg Likes, Avg Comments, Median Engagement Rate, Quality flag (Good / Poor).
- **Contact** — Email, Email Source, Phone, External URL, Physical Address.
- **Classification** — Business Category, Detected Language, Account Type.
- **Optional post sample** — captions of the 8 most recent posts, plus contacts parsed out of them.

Then **your filters** run — follower band, engagement floor, language, business category, contact-channel presence, posting cadence, Reels view ratio, verification — and only the matches are saved.

### ⚡ Quick start

A minimal input that works on the **free plan** (5 accounts, no setup):

```json
{
  "searchQueries": ["fitness coach"],
  "searchHashtags": ["personaltrainer"],
  "extractEmail": true
}
```

Leave **both** search fields empty and the run does a small capped demo search instead of failing, so you can see the output shape before deciding what to ask for.

### 📦 Output sample

Every analyzed account is pushed to the dataset as one item. Here is a real row from a real run — the search was `nike running` with a 50 000-follower floor (Profile Picture URL and post captions truncated for readability):

```json
{
  "Account": "https://instagram.com/nikerunning",
  "Source": "Keyword Discovery",
  "Full Name": "Nike Running",
  "Followers Count": 6187625,
  "Following Count": 599,
  "Biography": "Don't lose your cool. \nAero-FIT is available now.",
  "Email": "N/A",
  "Email Source": "N/A",
  "Phone": "N/A",
  "External URL": "http://empli.fi/nikerunning",
  "Category": "N/A",
  "Address": "N/A",
  "Profile Picture": "https://scontent.cdninstagram.com/v/t51.../profile.jpg",
  "Reels Count": 12,
  "Last Reel (Days Ago)": 0,
  "Median Views": 282564,
  "Avg Likes": 10634,
  "Avg Comments": 0,
  "Views/Followers Ratio": "4.57%",
  "Posts in Last 30 Days": 11,
  "Posts per Month": 11,
  "Total Posts": 2076,
  "Detected Language": "English",
  "Last Post Within (Days)": 0,
  "Median ER": "0.13%",
  "Quality": "Poor",
  "Post 1": "Introducing air conditioning for athletes. Aero-FIT keeps 2x Olympic Medalist…",
  "Post 2": "Don't lose your cool. No matter how hot it gets. Aero-FIT is coming soon.",
  "Post 3": "Beat the heat. Introducing Aero-FIT, air conditioning for athletes…",
  "Post 4": "Six cities. One starting line. Thousands of stories…",
  "Post 5": "After a 10-month hiatus, @jakobing takes 5000m gold in Birmingham. Welcome back.",
  "Post 6": "The harder you run, the harder you cool. Feel the airflow of Aero-FIT…",
  "Post 7": "\"I really feel the air when I pick up the pace.\" When @kenny_bednarek turns up…",
  "Post 8": "\"I don't feel the shirt. I feel air.\" For 100x Half-Marathon Champion Yin Xiao…",
  "Analysis Status": "analyzed",
  "Why Not Analyzed": "N/A"
}
```

That `"Quality": "Poor"` on a 6-million-follower brand account is the actor working, not failing: a 0.13 % engagement rate is what a huge follower count usually buys, and it is exactly the row you would want filtered out of an outreach list. Set `minEngagementRate` and it never reaches your dataset.

Missing optional values come back as the string `"N/A"` rather than `null`, so every key is always present and downstream code (Sheets, Airtable, CSV) can rely on a stable shape. The full per-column schema — types, descriptions, examples — is in [.actor/dataset\_schema.json](.actor/dataset_schema.json), which is also what an AI agent reads when it calls this actor through Apify's MCP server.

**On the free plan, the results also tell you what was left behind.** The free plan analyzes 5 discovered accounts per run. When a search term still had candidates left when the run stopped, the actor adds one extra row per term — `"Analysis Status": "not_analyzed"` and, in `Why Not Analyzed`, how many more accounts that term still had. Those rows come after your results, they are never charged, and a paid run never produces them.

### 🧭 When to use it

- **Influencer sourcing.** Name the niche, set a follower band (3 000–100 000 is the most common), and get creators in it with engagement rate already computed and emails already extracted.
- **Lead generation.** Search the category your buyers describe themselves with — `nutrition coach`, `dentist`, `wedding photographer` — and get their contact details in one pass.
- **Hashtag research.** Find who is actually behind a hashtag's top posts, not just the posts, then qualify them by audience size and engagement.
- **New-market entry.** Search in any language to build a first seed list in a country or vertical you have no accounts in yet.
- **Competitor-adjacent discovery.** Search the words your rivals use in their bios and see who else claims the same ground.

### 🎯 Example tasks

Ready-to-run examples — each opens a pre-configured task you can run in one click (no setup):

- **[Find influencers on Instagram by keyword](https://apify.com/afanasenko/instagram-influencer-search/examples/find-influencers-on-instagram-by-keyword)** — Search any niche and get the accounts in it, each with follower count, engagement rate, email, phone, website and business category.
- **[Find micro influencers by follower count](https://apify.com/afanasenko/instagram-influencer-search/examples/find-micro-influencers-by-follower-count)** — Set a follower range and a minimum engagement rate, and get creators in your niche that fit it, with contact details already attached.
- **[Build an Instagram influencer database](https://apify.com/afanasenko/instagram-influencer-search/examples/build-an-instagram-influencer-database)** — Run several niches at once and export one sheet: handle, followers, engagement rate, email, phone, website, category and Reels views.
- **[Find Instagram influencers with emails](https://apify.com/afanasenko/instagram-influencer-search/examples/find-instagram-influencers-with-emails)** — Keep only the accounts that publish a way to reach them. Every row carries the email plus audience size, engagement rate and category.
- **[Find Instagram creators by hashtag](https://apify.com/afanasenko/instagram-influencer-search/examples/find-instagram-creators-by-hashtag)** — Give it a hashtag and get the accounts behind its top posts, each with follower count, engagement rate and public contact details.

### 🛠 Input

The input form is grouped into four sections:

| Section | Purpose |
|---|---|
| **🎯 Find accounts by keyword or hashtag** | The search terms, how many pages to read per term, and the cost ceiling. |
| **⚙️ Data Extraction Options** | Which enrichments to run (email, phone, posts, engagement). Off = skip the call → faster and cheaper. |
| **🔬 Advanced Filtering (Optional)** | 20+ filters that drop non-matching accounts. |
| **▶️ Run & Storage Options** | Resume from checkpoint, offline re-filter mode, exclusion list. |

The fields that matter most:

- **`searchQueries`** — search terms, one per line. Single common words return far more candidates than long phrases.
- **`searchHashtags`** — hashtags, with or without `#`. Returns the authors of the hashtag's top posts.
- **`maxSearchPagesPerQuery`** — how deep to read each term's results (1–50, default 5). More pages = more candidates, slower.
- **`maxCountDiscovery`** — hard cost ceiling in accounts. Set it to your **spend budget × 100** (e.g. `1000` = $10).
- **`minFollowers` / `maxFollowers`** — the most-used filter, set as a band (3 000–100 000 for micro-influencers).
- **`minEngagementRate`** — a common floor is 1–3 %.
- **`analyzeQuality`** — on by default; computes Engagement Rate and the Quality flag.
- **`extractPosts`** — fetch the 8 most recent captions; required for `lastPostDays`, `minPostsInPeriod`, `keywordLocation=posts` and `searchContactsInPosts`.
- **`contactInfoType`** — keep only accounts that have the contact channel you will actually use.
- **`profileLanguage`** — restrict to one of 44 detected languages.

### 💰 Pricing

The actor uses Apify's **Pay Per Event** model with **one single event**:

| Event | Price | Triggered |
|---|---|---|
| **Profile** | **$0.01** | Once per discovered account that is successfully retrieved and analyzed, whether or not it passes your filters. |

Accounts that could not be read — not found, private, or failed — are not charged. You are billed per account, not per API call, so `maxCountDiscovery` translates directly into your maximum spend.

**Filters run after the fetch.** An account has to be read before the actor can tell whether it matches your follower band or language, so a narrow filter stack costs the same as a wide one and returns fewer rows. Start loose, look at the yield, then tighten — and use Offline Mode (below) to re-filter what you already paid for, free.

### 🆓 Free vs paid plan

| | Free plan | Paid plan |
|---|---|---|
| Accounts per run | 5 | unlimited |
| Search terms per run | unlimited | unlimited |
| Filters (followers, language, engagement, …) | ✓ | ✓ |
| Reels analytics (Median Views, Views/Followers) | blanked | full |
| Offline re-filtering | ✓ | ✓ |
| Resume from checkpoint | ✓ | ✓ |

Upgrade to a paid plan to remove the 5-account cap and to see Reels view analytics.

### 🧪 Filter recipes

**Micro-influencer sourcing (fitness / wellness)**

```json
{
  "searchQueries": ["fitness coach", "nutrition coach"],
  "searchHashtags": ["fitnesscoach", "personaltrainer"],
  "maxCountDiscovery": 500,
  "minFollowers": 3000,
  "maxFollowers": 100000,
  "minEngagementRate": 2,
  "extractEmail": true,
  "contactInfoType": "emailOrPhone",
  "filterForInfluencers": true
}
```

**Local-business lead list**

```json
{
  "searchQueries": ["dental clinic", "dentist", "orthodontist"],
  "maxCountDiscovery": 300,
  "accountType": "business",
  "extractPhysicalAddress": true,
  "locationKeywords": "London, Croydon, Wembley, Stratford, Camden, United Kingdom",
  "hasWebsite": true
}
```

`extractPhysicalAddress` adds the Address column so you can see exactly what each row matched — the filter itself works without it.

The Business-Address filter reads the address a business published about itself — not a place you search. Write it the way Instagram writes it: "Miami, Florida" in the US, Canada, Mexico and India (city, then state), "Berlin, Germany" everywhere else (city, then country in English). Six rules from our own run history:

- **Separate terms with a comma.** A space-separated list is read as one long term — of 21 runs that tried, one delivered.
- **Give it a list, not a word.** Name the city, the towns around it, and the region. Customers who wrote lists of six or more terms got rows 38% of the time; customers who never went past five, 11%. Terms are OR-ed — an extra term can only help, never hurt.
- **Add the region written out.** "Florida", "Ontario", "Germany", "Nigeria" — Instagram spells these in full; the field carries "United Arab Emirates", not "UAE", and a list of nothing but country abbreviations has not returned a row yet.
- **Copy Instagram's spelling, accents included.** "São Paulo", not "Sao Paulo".
- **Search for business types, not people.** "dental clinic" surfaces profiles with addresses; "fitness coach" surfaces creators, who have none.
- **Neighborhoods work too.** The street line is searched as well, so "Marina", "Lagos Island" or "Borivali West" can match where a city name is too broad.

**Non-English market entry**

```json
{
  "searchQueries": ["coach immobilier", "agent immobilier"],
  "maxCountDiscovery": 200,
  "profileLanguage": "French",
  "minFollowers": 1000,
  "extractEmail": true
}
```

### 🔁 Resume / checkpoint

Long runs can be interrupted (timeout, manual stop, abort). The actor writes a checkpoint after every batch. To resume, run it again with **`clearSavedData`** unchecked — accounts already analyzed are not re-billed.

### 📡 Live status & storage records

| Storage key | Type | What it holds |
|---|---|---|
| `status.html` | HTML page | Live progress, cost, ETA. Open it from the run's Storage tab. |
| `RUN_SUMMARY` | JSON | Aggregate run statistics — counts, plan, filter breakdown, upstream request totals. |
| `SKIPPED_ACCOUNTS` | JSON | Every account skipped, with reason and category (filter / not\_found / private / error). |
| `USER_MESSAGE` | JSON | The one thing this run most needs to tell you — a demo notice, a zero-result diagnosis, or a free-plan cap. |
| `FILTER_BURN_PREDICTION` | JSON | Written whenever a post-fetch filter is active: how much of the fetch your filter stack is likely to reject. |
| `API_USAGE` | JSON | Upstream request count for this run, split into fetches vs searches. |

### 🤖 Programmatic / API use

**REST API:**

```bash
curl -X POST "https://api.apify.com/v2/acts/afanasenko~instagram-influencer-search/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchQueries": ["fitness coach"],
    "searchHashtags": ["personaltrainer"],
    "maxCountDiscovery": 100,
    "minFollowers": 3000,
    "maxFollowers": 100000
  }'
```

After the run succeeds, read rows from its default dataset; run-level statistics live in the `RUN_SUMMARY` record of the same run.

**MCP / agentic clients (Claude, ChatGPT, Cursor, LangGraph, OpenAI Agents SDK, Mastra, …):**

The actor is exposed as a tool through Apify's [MCP server](https://docs.apify.com/platform/integrations/mcp) at `mcp.apify.com`. To mount it in your agent as a dedicated tool in one command:

```bash
apify mcp install claude-code --tools afanasenko/instagram-influencer-search
```

Then ask in natural language — *"find 50 fitness coaches with 10–50k followers and an engagement rate above 3%, with emails"* — and the agent fills the input schema itself.

### 💡 Tips & best practices

- **Start with no filters.** Over-filtering is the most common cause of an empty run. Search filterless once to see what the term's pool looks like, then narrow.
- **Filter offline, not online.** Accounts are discovered *before* filters run — on the free plan only 5 of them — so one strict filter can empty a run. Harvest filterless first, then turn on **Enable Offline Mode** to try any filter combination against the accounts already saved. Re-filtering makes no requests and charges nothing.
- **Combine keywords with hashtags.** They surface different populations: keyword search reads names and bios, hashtag search reads who posts under the tag. Customers who use both get the widest funnel.
- **Prefer short terms.** `fitness coach` returns an order of magnitude more candidates than `online fitness coach for women over 40`. Narrow with the filters, not with the query.
- **Raise `maxSearchPagesPerQuery` before adding terms.** Reading deeper into one good term is usually cheaper than adding a term that overlaps it.

### ❓ FAQ

**Q: How does the actor find accounts for a keyword?**
A: It queries Instagram's own account search for each term — the same search the app performs — and reads as many result pages as `maxSearchPagesPerQuery` allows. For hashtags it reads the hashtag's top posts and takes their authors.

**Q: Do I need an Instagram account, login, or cookies?**
A: No. You provide search terms and get public profile data back. No credentials of any kind are involved, so there is no risk to any Instagram account of yours.

**Q: Why did my search return so few accounts?**
A: Usually a long phrase. Instagram's search is biased toward short, high-volume terms. Try the two- or three-word version, add a hashtag, or raise `maxSearchPagesPerQuery`.

**Q: Are filtered-out accounts charged?**
A: Yes — an account must be fetched before it can be filtered, so it counts as one paid event even if a filter then rejects it. That is why the actor writes `FILTER_BURN_PREDICTION` before fetching and warns you when your filter stack looks too narrow.

**Q: How is engagement rate calculated?**
A: For each recent post, `(likes + comments) / followers`, then the median across the sample. The median resists viral outliers better than the mean.

**Q: What does the Quality flag mean?**
A: A heuristic combining engagement rate and audience signals. **Good** = worth reaching out to. **Poor** = likely low-engagement or inflated. A quick filter, not a verdict.

**Q: Why are my Reels metrics blank?**
A: Reels analytics require a paid plan. On the free plan those columns return `"N/A"`.

**Q: Will I get the same accounts for the same term across runs?**
A: Mostly, but not exactly. Instagram's search ranking shifts day to day. Re-running the same term a week later typically overlaps 70–90 % with the previous list.

**Q: Which input field names does the API expect?**
A: `searchQueries` and `searchHashtags` (arrays of strings), `maxSearchPagesPerQuery` and `maxCountDiscovery` (numbers). Common wrong guesses — `query`, `keyword`, `maxItems`, `maxResults`, or the seed fields from the six-mode Profile Scraper — are **not** recognized; the run log and the run report name them back to you with the field you probably meant.

**Q: Can I re-filter results without paying again?**
A: Yes. Turn on **Enable Offline Mode** and the actor re-applies your current filters to accounts cached from previous runs — no Instagram reads, no paid events.

**Q: Can I schedule it?**
A: Yes, on any plan including free. Save your input as a Task in Apify Console, then add a Schedule to the Task (⋮ menu → Schedule).

### 🔗 Other Instagram scrapers (same author)

Pick the one that matches what you start with:

| You start with… | You want to find… | Use this actor |
|---|---|---|
| A keyword or a hashtag | The accounts in that niche, enriched and filtered | **This actor** |
| 1–5 seed handles you like | Similar / suggested accounts in the same niche | [Instagram Related Profiles Scraper](https://apify.com/afanasenko/instagram-related-profiles-scraper) |
| One known account | Its full **followers** or **following** list, with filters and enrichment | [Instagram Followers & Following Extractor](https://apify.com/afanasenko/instagram-followers-scraper) |
| One known account | **Track** who follows / unfollows it over time (scheduled) | [Instagram Follower Tracker](https://apify.com/afanasenko/instagram-follower-tracker) |
| Anything else (handles, post links, locations, keywords) | All of the above plus five other discovery modes in one tool | [Instagram Profile Scraper](https://apify.com/afanasenko/instagram-profile-scraper) |
| A reel link or a creator handle | What their reels **say and show** — spoken transcript, on-screen text, hook and structure | [Instagram Reel Script Extractor](https://apify.com/afanasenko/instagram-reel-script-extractor) |
| An AI agent (Claude, Cursor, ChatGPT) | The same Instagram data from inside your agent — MCP tools it picks by intent | [Instagram Profile MCP Server](https://apify.com/afanasenko/instagram-profile-scraper-mcp-server) |

### 🛟 Support & feedback

- **Open an issue** on the actor's Issues tab in Apify Console — the fastest way to get a fix shipped.
- **Feature requests** in the same tab; we read every one.
- **Ratings & reviews** on the [Apify Store page](https://apify.com/afanasenko/instagram-influencer-search) help other users find the actor.

### ⚖️ Disclaimer

This actor reads **publicly available** Instagram profile data. It does not bypass authentication, read private profiles, or interact with content on your behalf. Use it in compliance with Instagram's Terms of Service and applicable privacy laws (GDPR, CCPA) — for outreach lists, make sure you have a legitimate interest and a clear unsubscribe path. The contact details returned are what the profile owner chose to publish on Instagram.

# Actor input Schema

## `searchQueries` (type: `array`):

Search terms, one per line. The actor searches Instagram account names and bios for each term, then applies your filters to the accounts it found. Single common words return far more candidates than long phrases. Works in any language. Example: fitness coach, veterinario, marketing agency.

## `searchHashtags` (type: `array`):

Instagram hashtags, one per line, with or without the # symbol. For each hashtag the actor collects the authors of its top posts — these skew larger and already-popular, so a follower floor keeps a much higher share than plain keyword search does. Combine with Search Queries to widen the top of the funnel. Example: fitnesscoach, personaltrainer.

## `maxSearchPagesPerQuery` (type: `integer`):

How many pages to fetch per search query and per hashtag. More pages = more candidates but slower discovery. Range 1–50. Default 5.

## `maxCountDiscovery` (type: `integer`):

Maximum number of unique accounts to analyze in this run — the hard cost ceiling, because each analyzed profile is one paid event. Free plan ceiling: 5 profiles. 0 = unlimited. Default 0.

## `extractEmail` (type: `boolean`):

When true, extracts public email addresses from each profile (Instagram Contact button + bio parse). Set false to skip email extraction. Default true. Populates the Email + Email Source columns.

## `extractPhoneNumber` (type: `boolean`):

When true, extracts public phone numbers from each profile (Instagram Contact button + bio parse). Set false to skip. Default false (most lead-gen workflows rely on email/website). Populates the Phone column when enabled.

## `extractWebsiteUrl` (type: `boolean`):

When true, extracts the bio-link URL from each profile. Set false to skip. Default true. Populates the External URL column.

## `extractBusinessCategory` (type: `boolean`):

When true, extracts the Instagram business category for business profiles (e.g. «Athlete», «Beauty, Cosmetic & Personal Care»). Set false to skip. Default true. Populates the Category column.

## `extractPhysicalAddress` (type: `boolean`):

When true, extracts the public street address shown on a business profile when disclosed. Default false. Populates the Address column.

## `analyzeQuality` (type: `boolean`):

When true, computes Median Engagement Rate and a coarse Quality score (Excellent/Good/Average/Poor) from recent posts, plus Reels analytics (median views, view/follower ratio) on every plan. Requires an extra API call per profile. Default true. Populates Median ER, Quality, Avg Likes, Avg Comments, Posts per Month columns.

## `minEngagementRate` (type: `integer`):

Minimum median engagement rate (%) — profiles below this are skipped. 0 = no filter (default). Engagement rate is computed from likes+comments on recent posts vs follower count; requires analyzeQuality=true.

## `extractPosts` (type: `boolean`):

When true, extracts caption text from the 8 most recent feed posts. Default false. Populates Post 1..Post 8 columns and is a prerequisite for searchContactsInPosts.

## `searchContactsInPosts` (type: `boolean`):

When true, scans the extracted post captions for emails and phone numbers (e.g. booking@brand.com referenced in a Reel description). Requires extractPosts to also be true. Default false. Populates Email from Posts + Phone from Posts columns.

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

Only process profiles containing **any** of these keywords. Not case-sensitive.

## `keywordLocation` (type: `string`):

Where to search for keywords — `bio_or_name` (default), `bio` only, `name` only, `posts` (recent post captions, requires post data), or `anywhere`. Choose `posts` for high-intent niche matching beyond profile metadata.

## `locationKeywords` (type: `string`):

Keeps a profile only if its public business address or city contains one of your terms — any single match keeps it.
• **Separate terms with a comma.** A space-separated list is read as one long term and almost never matches.
• **Only professional accounts publish an address** — so search for business types ("dental clinic"), not people ("fitness coach"). Used alone, this filter returns nothing on 3 runs out of 4.
• **Write a list, not one city** — "Miami, Fort Lauderdale, Boca Raton, Florida". Terms are OR-ed, so an extra term can only help: lists of six or more delivered four times as often as a single word.
• **Add the region in full, the way Instagram spells it** — the state in the US, Canada, Mexico and India ("Miami, Florida"), the country in English elsewhere ("Berlin, Germany"). The field carries "United Arab Emirates", not "UAE".
• **Copy Instagram's spelling** — accents included ("São Paulo", not "Sao Paulo"), and whole place names: short terms match inside longer words ("us" hits "Houston").
• **It does not search a place** — it reads what an account published about itself.
Leave empty for no location filter.

## `profileLanguage` (type: `string`):

Language filter — restrict results to profiles whose bio + post text was detected as this language. «any» (default) bypasses detection. Detection runs on bio + recent post captions via Google CLD3. Closely related languages can be mistaken for one another — Serbian written in Latin letters is usually detected as Croatian, and Malay as Indonesian.

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

Minimum follower count — profiles below this are skipped. 0 = no minimum (default). Filters run after each profile is fetched, so a floor set too high returns an empty run you still paid for. Start at 0, look at the follower counts you actually get back, then raise it.

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

Maximum follower count — profiles above this are skipped. 0 = no maximum (default). Useful for excluding mega-accounts, but a narrow min-max band is the fastest way to end up with zero rows - widen it if a run comes back empty. As a rule of thumb, keep the maximum at least 10x the minimum: bands tighter than that keep under 10% of the profiles they analyze, and you pay for the rest.

## `lastPostDays` (type: `integer`):

Activity recency filter — only include profiles that posted any feed content within the last X days. 0 = disabled (default). Drops dormant accounts. Requires post data.

## `lastReelDays` (type: `integer`):

Reel-activity recency filter — only include profiles that posted a Reel within the last X days. 0 = disabled (default). Useful for Reels-driven campaigns.

## `minPostsInPeriod` (type: `integer`):

Only process accounts with at least this many posts within the specified period. Set to 0 to disable. **Requires post data.**

## `postsCheckPeriodDays` (type: `string`):

The time period (in days) to check for the minimum number of posts.

## `minMedianViews` (type: `integer`):

Only process accounts where the median view count of their recent posts is greater than this number. Set to 0 to disable.

## `viewFollowerRatioMin` (type: `integer`):

Reject profiles whose median Reel views are below this % of their follower count. 0 = no minimum. For B2B targeting, 5 is a sensible floor.

## `viewFollowerRatioMax` (type: `integer`):

Reject profiles whose median Reel views are above this % of their follower count (filters out viral one-hit accounts). 0 = no maximum. For B2B targeting, 30 is a sensible ceiling.

## `contactInfoType` (type: `string`):

Contact-info filter — keep only profiles that have at least the requested contact data. «any» (default, no filter), «emailOrPhone», «emailOnly», «phoneOnly», «emailAndPhone». Runs independently of the extract-\* flags above. Combine with lead-gen workflows where you must have email or phone.

## `hasWebsite` (type: `boolean`):

When true, only profiles with a website link in their bio pass the filter. Default false. Useful for B2B / lead-gen lists where the link is a qualified-traffic signal.

## `accountType` (type: `string`):

Account-type filter — restrict to «business» profiles, «personal» profiles, or «any» (default, no filter). Most ecommerce / B2B targeting wants «business»; influencer discovery often wants «personal».

## `filterForInfluencers` (type: `boolean`):

When true, only profiles whose category matches an influencer-leaning list (e.g. Blogger, Artist, Public Figure, Digital Creator) pass the filter — helps automatically exclude most brands and organizations. Default false. Requires profile data.

## `categoryFilter` (type: `string`):

Business-category filter — restrict to profiles whose Instagram-set category matches this exact value (e.g. «Public Figure», «Beauty, Cosmetic & Personal Care», «Fitness Trainer»). «any» (default) = no filter. Independent of filterForInfluencers. MCP clients see only the first ~10 enum entries due to truncation; programmatic callers can pass any of the 1090+ exact values.

## `filterCombination` (type: `string`):

How to combine the Business Category filter and the Keywords filter when BOTH are set.
**AND** (default): a profile must match both filters (existing behavior).
**OR**: a profile passes if it matches **either** the category **or** any of the keywords. The output dataset adds a **Matched By** column showing which filter(s) let each profile through (`category`, `keyword`, or `both`).

## `mustBeVerified` (type: `boolean`):

When true, only verified (blue checkmark) accounts pass the filter. Default false. Useful for vetted-creator outreach lists; off by default since most creator audiences are unverified.

## `clearSavedData` (type: `boolean`):

Check this to clear all saved data from previous runs and start clean. Uncheck to resume a previous run from where it left off. Turning on Offline Mode keeps your saved profiles regardless of this setting.

## `enableOfflineMode` (type: `boolean`):

Re-filter the profiles a previous run already retrieved, without fetching anything new. Makes no API calls and charges nothing. Every profile a normal run retrieves is saved - including the ones your filters rejected - so if a run came back empty, turn this on, loosen a filter, and run again for free.

## `excludeAccounts` (type: `array`):

Usernames to skip BEFORE they are analyzed or charged — used for cross-run deduplication. Discovered candidates matching this list are dropped before any per-profile cost is incurred. Accepts bare handles, @handles, or profile URLs (one per line); matched case-insensitively. Leave empty for no exclusion. Does not apply to Mode 2 (explicit account lists).

## Actor input object example

```json
{
  "searchQueries": [],
  "searchHashtags": [],
  "maxSearchPagesPerQuery": 5,
  "maxCountDiscovery": 0,
  "extractEmail": true,
  "extractPhoneNumber": false,
  "extractWebsiteUrl": true,
  "extractBusinessCategory": true,
  "extractPhysicalAddress": false,
  "analyzeQuality": true,
  "minEngagementRate": 0,
  "extractPosts": false,
  "searchContactsInPosts": false,
  "keywords": [],
  "keywordLocation": "bio_or_name",
  "locationKeywords": "",
  "profileLanguage": "any",
  "minFollowers": 0,
  "maxFollowers": 0,
  "lastPostDays": 0,
  "lastReelDays": 0,
  "minPostsInPeriod": 0,
  "postsCheckPeriodDays": "30",
  "minMedianViews": 0,
  "viewFollowerRatioMin": 0,
  "viewFollowerRatioMax": 0,
  "contactInfoType": "any",
  "hasWebsite": false,
  "accountType": "any",
  "filterForInfluencers": false,
  "categoryFilter": "any",
  "filterCombination": "AND",
  "mustBeVerified": false,
  "clearSavedData": true,
  "enableOfflineMode": false,
  "excludeAccounts": []
}
```

# Actor output Schema

## `liveStatus` (type: `string`):

No description

## `results` (type: `string`):

No description

## `runSummary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("afanasenko/instagram-influencer-search").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("afanasenko/instagram-influencer-search").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 '{}' |
apify call afanasenko/instagram-influencer-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,afanasenko/instagram-influencer-search"
        }
    }
}

```

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/Hbm83vwuTX887kCYD/builds/IUcqn4SCydoSFOU3w/openapi.json
