# Instagram Boolean Search Scraper | Posts & Reels (`scraping_solutions/instagram-boolean-search-scraper-posts-reels`) Actor

Search Instagram posts and Reels using Boolean queries with AND, OR, NOT, phrases, keywords, and hashtags. Filter by date and engagement, deduplicate matches, and export structured JSON, CSV, Excel, or API data. No cookies required.

- **URL**: https://apify.com/scraping\_solutions/instagram-boolean-search-scraper-posts-reels.md
- **Developed by:** [Scraping Solutions](https://apify.com/scraping_solutions) (community)
- **Categories:**
- **Stats:** 5 total users, 3 monthly users, 85.3% runs succeeded, 0 bookmarks
- **User rating**: 1.00 out of 5 stars

## Pricing

from $1.35 / 1,000 matching instagram results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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 Boolean Search Scraper | Posts & Hashtags

Find public Instagram posts and Reels with one precise Boolean query instead of repeating many separate searches. The Actor automatically combines **keyword post search, paginated hashtag feeds, exact phrases, `AND`, `OR`, `NOT`, and parentheses**, then exports one clean, deduplicated dataset ready for research, monitoring, lead discovery, or content analysis.

No Instagram login or cookies are required.

> \[!IMPORTANT]
> **Search pages are billed even when they produce no final match.** Every successful Instagram search page costs **$0.01**. Restrictive `AND`, `NOT`, exact-phrase, date, or engagement filters can reject every candidate, so a run may return few or zero results while still incurring search-page charges. `resultsLimit` is a maximum, not a guaranteed result count. Start with **Efficient** coverage and a small limit, inspect the search plan, and broaden the expression if necessary.

> **Validate before running:** Build and check your expression with the free [FlujoDato Boolean Search Validator](https://flujodato.com/en/boolean-search-validator?platform=instagram). It detects syntax problems and previews the Instagram search plan before you consume Actor quota. [Abrir en español](https://flujodato.com/validador-busqueda-booleana?platform=instagram).

### What this Actor solves

Instagram search is useful for simple terms, but research questions are usually more specific:

```text
(#fitness OR "home workout") AND (protein OR nutrition) AND NOT giveaway
```

This Actor turns that expression into an executable search plan, discovers candidate content through Instagram, and applies the **complete Boolean expression** to each post locally. The result is one normalized dataset containing only matching public content.

Use it to:

- monitor brands, competitors, products, and campaigns;
- find niche creators and user-generated content;
- research conversations while excluding noise such as giveaways or job posts;
- combine several hashtags and phrases in one repeatable workflow;
- merge keyword and hashtag results so one search method does not hide useful content found by another;
- export qualified content to CSV, Excel, JSON, Google Sheets, or an API integration.

### Quick start

Use a simple hashtag:

```json
{
  "searchQuery": "#running",
  "resultsLimit": 100
}
```

Combine keywords and exact phrases:

```json
{
  "searchQuery": "(nike OR adidas) AND \"running shoes\" AND NOT giveaway",
  "resultsLimit": 200,
  "contentType": "posts_and_reels",
  "searchCoverage": "efficient"
}
```

Research recent Reels with engagement filters:

```json
{
  "searchQuery": "(#skincare OR \"skin care\") AND (review OR routine) AND NOT sponsored",
  "resultsLimit": 300,
  "contentType": "reels_only",
  "oldestPostDate": "2026-01-01",
  "minimumLikes": 100,
  "minimumViews": 1000
}
```

### Boolean syntax

| Syntax | Meaning | Example |
|---|---|---|
| `AND` | Every condition must match | `coffee AND ecuador` |
| `OR` | At least one condition must match | `nike OR adidas` |
| `NOT` | Exclude matching content | `fitness AND NOT giveaway` |
| `"..."` | Match an exact phrase | `"digital marketing"` |
| `( ... )` | Control grouping and precedence | `(saas OR software) AND b2b` |
| `-term` | Short form of `NOT term` | `travel -giveaway` |

Operators and matching are case-insensitive. Matching also ignores accents, so `CORRUPCION` matches `corrupción`. Precedence is `NOT`, then `AND`, then `OR`. Parentheses are recommended whenever a query mixes `AND` and `OR`.

Expressions such as `bank NOT jobs` are safely normalized to `bank AND NOT jobs` unless **Require explicit Boolean operators** is enabled.

### Validate your query before running

Open the free [FlujoDato Boolean Search Validator](https://flujodato.com/en/boolean-search-validator?platform=instagram) to check a query before it consumes Actor quota. A [Spanish version](https://flujodato.com/validador-busqueda-booleana?platform=instagram) is also available.

The validator runs in your browser and helps you:

- detect unbalanced parentheses, unfinished operators, and invalid expressions;
- normalize lowercase operators and missing implicit `AND` operators;
- see how many search combinations an `OR` expression creates;
- preview the Instagram execution plan before starting a paid extraction;
- test whether a sample caption matches the complete expression.

For example, paste this query into the validator:

```text
(nike OR adidas) AND (#running OR sneakers) AND NOT giveaway
```

After it is validated, use the same normalized expression as `searchQuery`:

```json
{
  "searchQuery": "(nike OR adidas) AND (#running OR sneakers) AND NOT giveaway",
  "resultsLimit": 100,
  "contentType": "posts_and_reels",
  "searchCoverage": "efficient"
}
```

The validator is a planning aid; the Actor always validates the query again before making provider requests.

### How discovery works

1. The Actor validates and normalizes the Boolean query before consuming provider requests.
2. It converts the expression into Boolean branches and automatically creates both keyword and hashtag searches from positive terms.
3. Up to three discovery searches run concurrently.
4. Candidate posts and Reels from both channels are merged and deduplicated by media ID or shortcode.
5. The complete expression is evaluated against the caption, hashtags, creator name, username, location, audio title, and artist metadata returned with each post.
6. Date, engagement, and content-type filters are applied.
7. Matching records are written to the default dataset immediately after every completed page.

Each page produces visible logs for the source, page number, provider request count, received items, matches, saved results, and Boolean rejections. The `RUN_PROGRESS` record is refreshed after every completed page. If a long run is stopped, previously written dataset rows and their result-event charges remain available.

The Actor rejects queries with no positive discovery term, such as `NOT giveaway`, and limits Boolean expansion to 32 branches to prevent unexpectedly expensive runs.

### Discovery channels

#### Keyword post search

Uses Instagram post or Reel search for every selected positive Boolean term. It accepts words, hashtags, and phrases.

#### Hashtag post feeds

Uses Instagram's paginated hashtag feed in addition to keyword search. A positive one-word term such as `running` is also searched as hashtag `#running`. Exact phrases containing spaces remain keyword searches because they are not valid Instagram hashtags.

Both channels always run automatically. There is no channel selector for the customer: the Boolean expression is the only search input. Results are merged and deduplicated before the complete expression is applied.

### Search coverage depth

#### Efficient

Uses one strong discovery term from each Boolean branch. This is the recommended default because it reduces provider requests while preserving the full Boolean filter locally.

To avoid paying for pagination that does not advance the query, each discovery search stops after **5 consecutive pages without a new matching post or Reel**. A candidate that is new but fails the Boolean expression, date range, or engagement filters does not reset this counter.

#### Comprehensive

Searches every positive hashtag, keyword, and phrase. Choose this when recall matters more than speed and upstream request usage.

Comprehensive coverage allows up to **20 consecutive pages without a new matching item** before stopping a discovery search. This wider window favors recall while still protecting the customer from indefinitely repeated or irrelevant provider pages.

Both modes stop immediately when the upstream provider repeats a pagination token.

The Actor enforces one exploration allowance for the **entire run**, not a separate allowance for every keyword or hashtag. It inspects at most **2x `resultsLimit` unique candidates globally**. The balanced page allowance starts from an estimate of 20 candidates per page and applies a 1.8x safety factor for duplicate-heavy or filtered feeds.

Pagination runs in two phases. The **coverage phase** gives every discovery source a fair initial allocation. The **adaptive phase** then continues only sources that have already produced matching results, five pages at a time, prioritizing recent and overall match yield. This avoids both extremes: allowing the first terms to monopolize the run or stopping productive historical searches at the same shallow per-source limit.

Instagram discovery is not a complete historical index. Comprehensive mode can improve coverage, but neither mode can guarantee every matching Instagram post.

### Input

| Field | Type | Default | Description |
|---|---:|---:|---|
| `searchQuery` | string | required | Hashtag, keyword, phrase, or Boolean expression. |
| `resultsLimit` | integer | `100` | Maximum unique matching results to save. |
| `contentType` | string | `posts_and_reels` | Search all public content or Reels only. |
| `hashtagFeedType` | string | `top` | Use top or recent hashtag content. |
| `searchCoverage` | string | `efficient` | Efficient or comprehensive discovery. |
| `oldestPostDate` | date | empty | Inclusive lower date in `YYYY-MM-DD`, applied after discovery. |
| `newestPostDate` | date | empty | Inclusive upper date in `YYYY-MM-DD`, applied after discovery. |
| `minimumLikes` | integer | `0` | Minimum reported likes. |
| `minimumComments` | integer | `0` | Minimum reported comments. |
| `minimumViews` | integer | `0` | Minimum reported video plays. |
| `strictBooleanSyntax` | boolean | `false` | Reject missing explicit operators instead of normalizing them. |

`resultsLimit` is a maximum, not a guarantee. Strict Boolean, phrase, date, or engagement filters can legitimately return fewer records or no records at all. The Actor scans up to **two times** the requested result limit across the **entire run** to compensate for filtered and duplicate candidates. Each successful search page is billed independently of how many candidates ultimately pass those filters.

Date filters do not instruct Instagram to begin at that historical date; they validate candidates after discovery. Setting the same old date in both fields searches for one exact calendar day, but a current Instagram feed may require substantial pagination before reaching it or may never expose it. Start with a wider date range and a small `resultsLimit`, then narrow it after confirming that the target period is discoverable.

### Pricing

This Actor uses two pay-per-event charges so strict filters remain sustainable without inflating the price of every saved result:

| Event | Free | Bronze | Silver | Gold |
|---|---:|---:|---:|---:|
| Saved result | $1.55 / 1,000 | $1.45 / 1,000 | $1.40 / 1,000 | $1.35 / 1,000 |
| Successful search page | $0.01 | $0.01 | $0.01 | $0.01 |

A search-page event is charged only after the Instagram data provider returns a valid response. **That page is charged even when every candidate on it is rejected by the Boolean expression or another filter.** Failed attempts and retries are not charged. A result event is charged only when a matching row is written to the default dataset. Platform usage is included and there is no Actor-start charge.

For example, 1,000 accepted results requiring 34 successful pages cost approximately `$1.55 + (34 x $0.01) = $1.89` on the Free tier. Boolean, date, or engagement filters can require more pages because rejected candidates are never billed as results.

An empty result is not necessarily a failed run. For example, if the Actor successfully scans 13 pages but all discovered candidates fail a restrictive expression, the customer pays `13 x $0.01 = $0.13` for search pages and `$0` for results. Use the Boolean validator, begin with **Efficient** coverage, and test 10-50 results before starting a large run.

Before making the first provider request, the Actor checks the **combined planned maximum** cost of saved-result events and successful search-page events against the run's `maxTotalChargeUsd`. The preflight assumes 20 discovered items per page, a **global 2x candidate scan allowance**, and a 1.8x page safety factor for duplicates and filters. The resulting page count is enforced as the shared runtime exploration limit. If the available run charge is insufficient, the Actor stops without consuming provider quota, stores `RUN_PROGRESS.status` as `budget_rejected`, and reports the required maximum, available amount, and shortfall.

The estimate and allocation strategy are visible in `SEARCH_PLAN`, `RUN_PROGRESS`, `RUN_SUMMARY`, and the log. The planned maximum is not a final quote: stale, empty, exhausted, or repeated feeds usually stop earlier. During execution, the Actor also stops gracefully when another page or result can no longer be charged. Results are streamed after each page, so already delivered rows are charged and retained even if a long run is stopped later.

#### Hashtag download limit

The upstream provider does not document a fixed total maximum for a hashtag feed. In a controlled pagination test, one hashtag returned **696 unique posts across 25 pages and still supplied a continuation cursor**. Pages contained approximately 24-30 posts. Therefore, the practical total depends on the hashtag's available public content, upstream pagination, run time, request quota, filters, and budget. This Actor applies its own explicit maximum of **10,000 saved results per run**.

### Output example

```json
{
  "query": "(#fitness OR \"home workout\") AND nutrition AND NOT giveaway",
  "normalizedQuery": "(#fitness OR \"home workout\") AND nutrition AND NOT giveaway",
  "matchedTerms": ["#fitness", "nutrition"],
  "discoveryType": "hashtag",
  "discoveryQuery": "fitness",
  "postId": "1234567890123456789",
  "shortCode": "ABC123xyz",
  "url": "https://www.instagram.com/reel/ABC123xyz/",
  "contentType": "reel",
  "caption": "A practical nutrition guide for runners #fitness",
  "hashtags": ["#fitness"],
  "publishedAt": "2026-08-20T14:30:00Z",
  "likeCount": 820,
  "commentCount": 41,
  "viewCount": 18400,
  "shareCount": 63,
  "username": "example.creator",
  "fullName": "Example Creator",
  "profileUrl": "https://www.instagram.com/example.creator/",
  "locationName": "Guayaquil",
  "locationId": "212999109",
  "audioId": "123456789012345",
  "audioTitle": "Espresso",
  "audioArtist": "Sabrina Carpenter",
  "scrapedAt": "2026-08-30T16:00:00Z"
}
```

The **Boolean search plan** output explains the normalized expression, branch count, generated discovery searches, and syntax warnings. **Live run progress** is updated after every completed page, while the **run summary** provides the final scanned items, duplicates, filter rejections, provider requests, saved results, stale-pagination stops, and repeated-cursor stops.

### Run with the Apify API

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/YOUR_USERNAME~instagram-boolean-search-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchQuery": "(#fitness OR #running) AND nutrition AND NOT giveaway",
    "resultsLimit": 100,
    "searchCoverage": "efficient"
  }'
```

### Reliability and limits

- Temporary upstream errors and rate limits are retried after 3, 9, and 27 seconds.
- Only successful provider pages are charged; failed retries are never billed as search pages.
- Results are deduplicated across every generated discovery search.
- Only public content available through Instagram discovery can be returned.
- Deleted, private, restricted, or unavailable content cannot be recovered.
- Engagement counters and media URLs reflect the values available at collection time.
- Media URLs can expire; use the permanent Instagram post URL for long-term references.

### Responsible use

Use public data responsibly and comply with applicable laws, privacy requirements, Instagram terms, and Apify policies. Do not use the Actor for harassment, unauthorized profiling, or decisions that produce legal or similarly significant effects about individuals.

### Support

When reporting an issue, include the Actor run ID, the input with secrets removed, the expected behavior, and one public example URL when available. Never send account passwords, cookies, or API tokens.

# Actor input Schema

## `searchQuery` (type: `string`):

Examples: #fitness; digital marketing; (#fitness OR "home workout") AND nutrition AND NOT giveaway. More AND, NOT, phrase, date, or engagement restrictions can require additional paid search pages while producing fewer matches. Check the expression before running with the free [FlujoDato Boolean Search Validator](https://flujodato.com/en/boolean-search-validator?platform=instagram).

## `resultsLimit` (type: `integer`):

Maximum number of unique Instagram posts or Reels saved after all filters. This is not a guaranteed result count. Successful search pages are charged separately, including pages whose candidates are all rejected.

## `contentType` (type: `string`):

Search all public posts and Reels, or limit discovery to Reels.

## `hashtagFeedType` (type: `string`):

Order used when a Boolean branch is discovered through a hashtag. Reels-only searches automatically use the Reels feed.

## `searchCoverage` (type: `string`):

Efficient uses the strongest discovery term from each Boolean branch and is recommended for first runs. Comprehensive searches every positive term for higher recall. The Actor first gives every source fair coverage, then reallocates the remaining global page allowance to searches that are producing matches. Restrictive expressions may still return few or zero matches.

## `oldestPostDate` (type: `string`):

Optional inclusive start date in YYYY-MM-DD format. This filter is applied after Instagram discovery; the provider cannot jump directly to an old date, so narrow historical ranges may return fewer matches.

## `newestPostDate` (type: `string`):

Optional inclusive end date in YYYY-MM-DD format. Using the same historical date in both fields requests one calendar day, but Instagram discovery still starts from the feed exposed by the provider.

## `minimumLikes` (type: `integer`):

Save only content with at least this many likes. Use 0 to disable the filter.

## `minimumComments` (type: `integer`):

Save only content with at least this many comments. Use 0 to disable the filter.

## `minimumViews` (type: `integer`):

Save only Reels or videos with at least this many reported plays. Non-video posts are excluded when this value is above 0.

## `strictBooleanSyntax` (type: `boolean`):

Reject implicit expressions such as 'bank NOT jobs'. Leave disabled to normalize them to 'bank AND NOT jobs' with a warning.

## Actor input object example

```json
{
  "searchQuery": "(#fitness OR \"home workout\") AND (protein OR nutrition) AND NOT giveaway",
  "resultsLimit": 100,
  "contentType": "posts_and_reels",
  "hashtagFeedType": "top",
  "searchCoverage": "efficient",
  "oldestPostDate": "",
  "newestPostDate": "",
  "minimumLikes": 0,
  "minimumComments": 0,
  "minimumViews": 0,
  "strictBooleanSyntax": false
}
```

# Actor output Schema

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

All matching posts and Reels in the default dataset.

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

Readable table with content, creator, engagement, and Boolean match information.

## `searchPlan` (type: `string`):

Normalized query, diagnostics, and upstream discovery searches generated from the Boolean expression.

## `runSummary` (type: `string`):

Counts for scanned, matched, filtered, duplicate, and requested records.

## `runProgress` (type: `string`):

Latest completed-page counters retained even when a long run is stopped.

# 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("scraping_solutions/instagram-boolean-search-scraper-posts-reels").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("scraping_solutions/instagram-boolean-search-scraper-posts-reels").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 scraping_solutions/instagram-boolean-search-scraper-posts-reels --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraping_solutions/instagram-boolean-search-scraper-posts-reels"
        }
    }
}

```

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/eQTLcwfumExPUhrs1/builds/He9KQ30m6WTzWSLqZ/openapi.json
