# Instagram Keyword Search Scraper (`automation-lab/instagram-keyword-search-scraper`) Actor

Discover public Instagram posts, Reels, and associated accounts from general keywords, with captions, engagement, media, and source-query metadata.

- **URL**: https://apify.com/automation-lab/instagram-keyword-search-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 10 total users, 6 monthly users, 59.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event + usage

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/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 Keyword Search Scraper

Discover public Instagram posts, Reels, and associated accounts from general keywords. **Instagram Keyword Search Scraper** turns phrases such as `specialty coffee`, `home coffee roasting`, or `latte art` into typed records with captions, public engagement, creator identity, media links, and source-query metadata.

The Actor is designed for repeatable trend research, creator discovery, content ideation, and public-market monitoring. It does not require an Instagram login or ask users for account cookies.

### What does this Instagram keyword search Actor do?

For every keyword, the Actor:

1. Resolves the phrase to relevant public Instagram hashtag topics.
2. Selects the highest-volume related topics.
3. Opens Instagram's public topic results in a real browser.
4. Extracts unique public post and Reel cards.
5. Links content to the associated public account identity.
6. Saves the original keyword, matched hashtag, source page, and position on every row.

This makes results auditable: you can always see why a record appeared.

### Who is it for?

- **Social media researchers** comparing themes and visible engagement.
- **Creator partnership teams** finding accounts active in a niche.
- **Coffee, fashion, travel, and consumer brands** collecting public content examples.
- **Agencies** building repeatable client research exports.
- **Analysts and data teams** loading Instagram discovery records into Sheets, a warehouse, or BI tooling.
- **AI workflows** that need typed public content records rather than screenshots.

### Why use this Actor?

- Search with general phrases, not only exact usernames or URLs.
- Return both content and associated account records in one dataset.
- Preserve keyword and matched-topic provenance.
- Normalize compact engagement such as `36.3K` to `36300` while retaining the original text.
- Deduplicate content URLs and accounts across related topics.
- Stop at the requested result limit.
- Fail clearly when Instagram returns a challenge or no usable records instead of silently succeeding with an empty dataset.
- Use the configured Apify Proxy for cloud reliability, with a bounded direct fallback.

### What data is extracted?

| Field | Meaning |
| --- | --- |
| `type` | `post`, `reel`, or `account` |
| `recordId` | Content shortcode or account username |
| `url` | Canonical public Instagram result URL |
| `username` | Associated public account username |
| `profileUrl` | Canonical account URL |
| `profileImageUrl` | Public profile image URL, when exposed |
| `caption` | Caption displayed on the public topic card |
| `hashtags` | Hashtags parsed from the caption |
| `mentions` | Mentioned usernames parsed from the caption |
| `engagementLabel` | Metric name shown by Instagram, such as `views` |
| `engagementCount` | Normalized numeric metric |
| `engagementText` | Original compact metric, such as `36.3K` |
| `imageUrl` | Public image or thumbnail URL, when exposed |
| `videoUrl` | Public video URL when Instagram exposes it |
| `matchedKeyword` | Original input keyword |
| `matchedHashtag` | Related topic used for discovery |
| `sourcePageUrl` | Instagram public topic page |
| `position` | One-based card position |
| `scrapedAt` | Collection time in ISO 8601 format |

Fields can be null when Instagram does not expose them on a public card. Media CDN URLs may expire; store the canonical Instagram URL as the durable reference.

### Getting started

1. Open the Actor input page.
2. Add one to ten real keywords.
3. Choose a maximum result count.
4. Select posts and Reels, accounts, or both.
5. Keep the recommended US residential proxy fallback enabled for cloud reliability.
6. Click **Start**.
7. Open the **Dataset** tab to inspect, download, or integrate the results.

A useful first input is:

```json
{
  "keywords": ["specialty coffee", "home coffee roasting"],
  "maxItems": 30,
  "maxHashtagsPerKeyword": 2,
  "resultTypes": ["content", "account"],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

### Input parameters

#### `keywords`

Required array of one to ten non-empty general phrases. Keywords are resolved to related Instagram topics; they do not need a leading `#`.

#### `maxItems`

Maximum combined number of unique rows. The limit applies across every keyword and both selected entity types. Allowed range: 1–500. Default: 30.

#### `maxHashtagsPerKeyword`

How many of the highest-volume related Instagram topics to inspect per keyword. Allowed range: 1–5. More topics improve breadth but require more browser work. Default: 2.

#### `resultTypes`

Choose `content`, `account`, or both. `content` includes posts and Reels. `account` emits one unique identity row per associated public creator found.

#### `proxyConfiguration`

Optional Apify Proxy configuration. The prefill enables US residential routing for cloud reliability; if that configured route fails, the Actor makes one bounded direct fallback attempt.

### Output example

The following is anonymized but matches the current output contract:

```json
{
  "type": "reel",
  "recordId": "DAbCdEf12xY",
  "url": "https://www.instagram.com/reel/DAbCdEf12xY/",
  "username": "example_roastery",
  "profileUrl": "https://www.instagram.com/example_roastery/",
  "caption": "A small-batch roast for a bright morning cup. #specialtycoffee",
  "hashtags": ["specialtycoffee"],
  "mentions": [],
  "engagementLabel": "views",
  "engagementCount": 36300,
  "engagementText": "36.3K",
  "matchedKeyword": "specialty coffee",
  "matchedHashtag": "specialtycoffee",
  "sourcePageUrl": "https://www.instagram.com/popular/specialtycoffee/",
  "position": 1,
  "scrapedAt": "2026-01-15T12:00:00.000Z"
}
```

Associated account rows use `type: "account"`. Content-only fields are null or empty on those rows.

### How much does it cost to search Instagram by keyword?

The Actor uses pay-per-event pricing:

- **Start:** $0.013 once per run.
- **Result item:** tiered by your Apify plan. The BRONZE price is $0.003464 per saved content or account row, with lower rates on higher plans.

At the BRONZE rate:

| Saved results | Actor events |
| ---: | ---: |
| 10 | about 0.0476 USD including start |
| 100 | about 0.3594 USD including start |
| 500 | about 1.745 USD including start |

Apify platform usage and residential proxy transfer can be passed through separately. Actual cost depends on the number of topics opened, page behavior, selected proxy, and run time. The run never charges an item event for a rejected or duplicate card.

### Search and creator-research workflows

#### One-time trend scan

Search a broad phrase, request content rows, and sort by `engagementCount` to inspect currently visible public examples.

#### Creator discovery

Select both result types. Group content by `username`, then use account rows as a unique creator list with a direct public profile URL.

#### Recurring monitoring

Schedule the same input daily or weekly. Store each run's dataset and compare `recordId`, `engagementCount`, and `scrapedAt` downstream. The Actor does not maintain historical state or send alerts by itself.

#### Spreadsheet or warehouse export

Download JSON, CSV, Excel, XML, or RSS from the Dataset tab, or consume dataset items through the Apify API.

### JavaScript API example

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/instagram-keyword-search-scraper').call({
  keywords: ['specialty coffee'],
  maxItems: 30,
  maxHashtagsPerKeyword: 2,
  resultTypes: ['content', 'account']
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Python API example

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/instagram-keyword-search-scraper').call(run_input={
    'keywords': ['home coffee roasting'],
    'maxItems': 20,
    'resultTypes': ['content'],
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### cURL API example

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~instagram-keyword-search-scraper/runs?token=$APIFY_TOKEN&waitForFinish=120" \
  -H 'Content-Type: application/json' \
  -d '{"keywords":["latte art"],"maxItems":20,"resultTypes":["content","account"]}'
```

Fetch dataset items using the `defaultDatasetId` returned by the run.

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/instagram-keyword-search-scraper"
```

For **Claude Desktop**, add this server to your MCP configuration. **Cursor** and **VS Code** can use the same remote-server JSON:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/instagram-keyword-search-scraper"
    }
  }
}
```

Example prompts:

- “Find public Instagram posts and Reels for specialty coffee and summarize recurring themes.”
- “Build a unique list of accounts associated with home coffee roasting.”
- “Compare visible engagement across latte art and coffee roasting content.”

### Integrations

Use Apify integrations to send completed datasets to:

- Google Sheets
- Make
- Zapier
- Slack
- Webhooks
- Amazon S3
- Google Drive
- a custom API or data warehouse

For monitoring, trigger a downstream workflow after each scheduled run and compare stable `recordId` values.

### Limits and expected behavior

- Results come from public, logged-out Instagram topic surfaces.
- A general keyword is mapped to related hashtags, so this is relevance discovery rather than an exhaustive full-text index.
- Instagram chooses and orders the public cards.
- The public surface can favor Reels for some topics.
- Private accounts and private content are not accessed.
- Login-only search history, contacts, followers, and private engagement are not included.
- Captions or metrics may be absent when Instagram omits them.
- Media CDN URLs can expire.
- The maximum result limit counts both content and account rows when both are selected.
- Instagram can change its public UI or anti-automation behavior.

### Reliability and troubleshooting

The Actor validates expected page shapes and retries a failed route through the configured proxy. It uses conservative browser concurrency and blocks heavy images, video, and fonts while preserving public metadata.

If a run produces no usable records, it exits as failed rather than masking the upstream problem.

#### Why did my run return fewer rows than `maxItems`?

The public topic may expose fewer unique cards or accounts than requested. Deduplication across topics can also reduce the total. Try a broader keyword, inspect more topics per keyword, or select both result types.

#### Why did direct mode fail?

Instagram can challenge datacenter addresses or vary public surfaces by geography. Enable Apify Proxy with the `RESIDENTIAL` group and `US` country fallback.

#### Why is `videoUrl` null on a Reel?

Instagram does not always expose a durable video CDN URL in the public topic card. Use the canonical `url` to reference the Reel.

### Responsible use and legality

Only collect public information you have a lawful reason to process. Follow Instagram's terms, applicable privacy and database laws, intellectual-property rules, and your organization's policies. Do not use this Actor to access private accounts, evade authentication, profile sensitive traits, harass people, or send unsolicited messages. Minimize retention of personal data and honor deletion or objection requests where required.

This tool provides technical access to public pages; it does not provide legal advice.

### FAQ

#### Does it require my Instagram password or cookie?

No. The selected workflow uses public logged-out topic surfaces and does not accept Instagram credentials.

#### Can it search several keywords in one run?

Yes, up to ten. Every row records the input keyword that produced it.

#### Does it return both posts and Reels?

Yes, when those content types appear in the selected public topics. The `type` field distinguishes them.

#### Can I return only creators?

Yes. Set `resultTypes` to `["account"]`.

#### Does it download media files?

No. It returns public media or thumbnail URLs when available and always preserves the canonical Instagram result URL.

#### Is this a historical Instagram database?

No. It collects the public topic surface visible during the run. Schedule runs and retain datasets if your lawful workflow needs change tracking.

### Related Actors

Explore other public-source tools from [automation-lab on Apify](https://apify.com/automation-lab). Choose an Actor whose source and output contract match your workflow; this Actor is specifically for keyword-led public Instagram topic discovery.

# Actor input Schema

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

General topics, niches, brands, or phrases to search. Enter up to 10 non-empty keywords.

## `maxItems` (type: `integer`):

Maximum combined number of unique content and account records saved across all keywords.

## `maxHashtagsPerKeyword` (type: `integer`):

Number of the highest-volume related public Instagram hashtag topics to inspect for each keyword.

## `resultTypes` (type: `array`):

Choose whether to return public posts and Reels, associated account identities, or both.

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

Optional Apify Proxy fallback for Instagram routes that do not return useful public data directly. Residential US routing is recommended for cloud reliability.

## Actor input object example

```json
{
  "keywords": [
    "specialty coffee",
    "home coffee roasting"
  ],
  "maxItems": 20,
  "maxHashtagsPerKeyword": 2,
  "resultTypes": [
    "content",
    "account"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset containing all typed Instagram keyword matches.

# 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": [
        "specialty coffee",
        "home coffee roasting"
    ],
    "maxItems": 20,
    "maxHashtagsPerKeyword": 2,
    "resultTypes": [
        "content",
        "account"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/instagram-keyword-search-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": [
        "specialty coffee",
        "home coffee roasting",
    ],
    "maxItems": 20,
    "maxHashtagsPerKeyword": 2,
    "resultTypes": [
        "content",
        "account",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/instagram-keyword-search-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": [
    "specialty coffee",
    "home coffee roasting"
  ],
  "maxItems": 20,
  "maxHashtagsPerKeyword": 2,
  "resultTypes": [
    "content",
    "account"
  ]
}' |
apify call automation-lab/instagram-keyword-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/instagram-keyword-search-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/99TdpvE6MCiKhnXcg/builds/ZXzAQIWcEQvVB0br6/openapi.json
