# Instagram Hashtag Scraper - Filtered Post Search (`scrapesage/instagram-hashtag-scraper`) Actor

Search Instagram hashtags and keywords without login, with filters that run inside the crawl: date range, minimum likes, comments and plays, media type and hashtag exclusions. Full post records with engagement, owner, location and coordinates. Monitor mode.

- **URL**: https://apify.com/scrapesage/instagram-hashtag-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Social media, Automation, SEO tools
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 post discovereds

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 Hashtag Scraper - Filtered Post Search

Search Instagram **hashtags and keywords without a login** and get back only the posts you actually want - filtered by **date range, minimum likes, minimum comments, minimum plays, media type and excluded hashtags**.

### Why this one

The popular hashtag scrapers take a four-field input (hashtags, result type, limit, keyword) and hand you a firehose you then filter yourself. That means your result limit gets eaten by posts you were going to throw away, and you pay for every one of them.

**This actor filters inside the crawl loop.** Set `minPlays: 500000` and your 100-result budget returns 100 posts that actually cleared half a million plays. Cheap filters (plays, excluded hashtags) are applied to the discovery payload **before** any paid detail fetch, so posts you filtered out cost you nothing.

| | This actor |
|---|---|
| Date range filter | ✅ `postedAfter` / `postedBefore` |
| Engagement floors | ✅ `minLikes`, `minComments`, `minPlays` |
| Media-type filter | ✅ image / video / reel / carousel |
| Hashtag exclusions | ✅ drop `#ad`, `#giveaway`, … |
| Keyword search | ✅ multi-word phrases |
| Filters applied before billing | ✅ |
| Location with coordinates | ✅ name, id, lat, lng |
| Login required | ❌ never |

### What you get per post

`postUrl` · `shortCode` · `mediaId` · `mediaKind` (image/video/reel/carousel) · `isReel` · `caption` · `hashtags[]` · `mentions[]` · `likeCount` · `commentCount` · `playCount` · `engagementRate` · `countsHidden` · `postedAt` · `takenAtTimestamp` · `thumbnailUrl` · `videoUrl` · `width` · `height` · `hasAudio` · `accessibilityCaption` · `locationName` · `locationId` · `locationLat` · `locationLng` · `coauthors[]` · `taggedUsers[]` · `ownerUsername` · `ownerFullName` · `ownerId` · `ownerIsVerified` · `ownerProfilePicUrl` · `ownerProfileUrl` · `query` · `queryType` · `scrapedAt`

### Input

```json
{
  "hashtags": ["travel", "vanlife"],
  "keywords": ["sourdough starter"],
  "minPlays": 500000,
  "postedAfter": "2026-06-01",
  "excludeHashtags": ["ad", "sponsored"],
  "mediaType": "reel",
  "maxResults": 100,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

| Field | What it does |
|---|---|
| `hashtags` | Tags to search, with or without `#` |
| `keywords` | Multi-word phrases (matched as Instagram tags) |
| `mediaType` | `all` / `image` / `video` / `reel` / `carousel` |
| `postedAfter` / `postedBefore` | Date window (`YYYY-MM-DD`) |
| `minLikes` / `minComments` | Engagement floors (need post details) |
| `minPlays` | Video play floor - applied **before** any paid detail fetch |
| `excludeHashtags` | Drop posts carrying these tags |
| `includePostDetails` | Adds likes, comments, exact date, location, tagged users, owner. On by default |
| `maxResults` | Total cap across all queries. `0` = no limit |
| `onlyNewPosts` | Monitor mode for brand tracking on a schedule |

### Honest limits - read before you buy

**Instagram gates some hashtags for logged-out visitors.** This is the single most important thing to know, so here is the measurement rather than a promise. Across a 16-tag sample (2 attempts each, fresh residential IP per attempt) on 2026-07-30:

- **12 of 16 tags returned data** (22 of 32 attempts).
- Reliable on every attempt: `#travel`, `#nature`, `#vanlife`, `#yoga`, `#crossfit`, `#homedecor`, `#streetphotography`, `#sourdoughstarter`, `#marathontraining`, `#specialtycoffee`.
- Intermittent (recovered on retry): `#dogsofinstagram`, `#skincareroutine`.
- **Login-walled on every attempt: `#sunset`, `#coffee`, `#food`, `#fitness`.**

The actor retries a walled tag up to 4 times on fresh IPs, and if Instagram still refuses it says so in the run status and bills you **nothing** for that tag. Specific tags behave better than ultra-generic one-word tags.

Other limits:

- **Instagram's logged-out discovery returns 12-18 posts per tag.** Volume comes from breadth - pass many tags/keywords - not from deep pagination, which requires a rotating internal token this actor deliberately does not hardcode.
- **Keywords are matched as tags.** `"sourdough starter"` is resolved to `#sourdoughstarter`. Instagram's logged-out keyword-search endpoint is a login wall on every request, so routing keywords through the tag lane is the only version of this feature that actually returns data.
- **`playCount`, `videoUrl` and `hasAudio` are video-only** - null on image and carousel posts by definition.
- **No sponsorship flag.** Instagram does not expose `is_paid_partnership` to logged-out callers (probed across 8 posts, zero sponsorship keys), so rather than ship a column that is always null, this actor omits it. Use `excludeHashtags: ["ad","sponsored"]` for a caption-level proxy.

### Pricing (pay per event, no start fee)

| Event | Price | What it covers |
|---|---|---|
| `post` | **$0.0025** | One matching post: caption, hashtags, play count, thumbnail, owner handle |
| `postDetail` | **$0.008** | Adds likes, comments, exact date, dimensions, location + coordinates, tagged users, collaborators, full owner record |

Posts are billed **before** they are written, and filtered-out posts are never billed at all.

### Use with AI assistants (MCP)

This actor works as a tool for LLM agents through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) - ask for "travel Reels over 500k plays from June" and it can call this actor directly.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### Integrations

[Make](https://apify.com/integrations/make), [Zapier](https://apify.com/integrations/zapier), [Slack](https://apify.com/integrations/slack), [Google Drive](https://apify.com/integrations/google-drive), [Airbyte](https://apify.com/integrations/airbyte), [GitHub](https://apify.com/integrations/github), the [Apify API](https://docs.apify.com/api/v2), [Schedules](https://docs.apify.com/platform/schedules) and [Webhooks](https://docs.apify.com/platform/integrations/webhooks).

### Monitor mode

Set `onlyNewPosts: true` and the actor remembers which posts it has already returned for that query set, emitting only new ones - a clean brand-monitoring feed when paired with [Apify Schedules](https://docs.apify.com/platform/schedules).

### FAQ

**Do I need a login or cookies?** No.

**Why did one of my tags return nothing?** Instagram serves a login wall for some tags to logged-out visitors (see the measured list above). The run still succeeds, says so in the status, and bills nothing for that tag.

**Why are likes null?** You ran with `includePostDetails: false`. Likes, comments and the exact date live on the post page, not in the discovery payload.

**Can I filter by language?** Not reliably - Instagram does not expose a language field logged-out, and guessing from caption text would be a false promise.

### Related scrapers by scrapesage

- [Instagram Reels Scraper](https://apify.com/scrapesage/instagram-reels-scraper) - play counts, view counts and Reel analytics
- [Facebook Ad Library Scraper](https://apify.com/scrapesage/facebook-ad-library-scraper) - Meta ad creatives and advertiser intel
- [Threads Scraper](https://apify.com/scrapesage/threads-scraper) - profiles, posts and replies
- [TikTok Scraper](https://apify.com/scrapesage/tiktok-scraper) - hashtag and creator analytics on TikTok

# Actor input Schema

## `hashtags` (type: `array`):

Hashtags to search, with or without the # (e.g. travel, streetphotography). Instagram's logged-out discovery returns its top posts per tag.

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

Free-text keyword searches (e.g. "sourdough starter"). Uses Instagram's keyword discovery rather than an exact tag.

## `mediaType` (type: `string`):

Restrict results to one media type. Requires post details for reliable classification.

## `postedAfter` (type: `string`):

Only posts on or after this date (YYYY-MM-DD). Needs post details, which carry the timestamp, so it switches them on automatically.

## `postedBefore` (type: `string`):

Only posts on or before this date (YYYY-MM-DD).

## `minLikes` (type: `integer`):

Skip posts below this like count. Needs post details.

## `minComments` (type: `integer`):

Skip posts below this comment count. Needs post details.

## `minPlays` (type: `integer`):

Skip videos/Reels below this play count. Applied to the discovery payload BEFORE any paid detail fetch, so filtered posts cost you nothing.

## `excludeHashtags` (type: `array`):

Drop any post whose caption carries one of these hashtags (e.g. ad, sponsored, giveaway).

## `includePostDetails` (type: `boolean`):

Fetches each post's own page to add like count, comment count, exact post date, dimensions, location, tagged users, collaborators and the full owner record. Billed as the postDetail event. Turn off for a cheap discovery-only pull.

## `maxResults` (type: `integer`):

Total posts to return across all queries. 0 means no limit (the run's time budget stops it safely).

## `onlyNewPosts` (type: `boolean`):

Remembers posts already returned for this query set and emits only unseen ones. Ideal on a schedule for brand monitoring.

## `detailConcurrency` (type: `integer`):

Parallel detail fetches. Keep at 4 or below - hashtag pages are Instagram's most rate-limited surface.

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

RESIDENTIAL is the tested default and strongly recommended for hashtag pages.

## Actor input object example

```json
{
  "hashtags": [
    "travel"
  ],
  "mediaType": "all",
  "minLikes": 0,
  "minComments": 0,
  "minPlays": 0,
  "includePostDetails": true,
  "maxResults": 100,
  "onlyNewPosts": false,
  "detailConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every matching post with likes, comments, plays, engagement rate, caption, hashtags, mentions, media type, owner and location as JSON items in the default dataset.

# 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 = {
    "hashtags": [
        "travel"
    ],
    "mediaType": "all",
    "includePostDetails": true,
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/instagram-hashtag-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 = {
    "hashtags": ["travel"],
    "mediaType": "all",
    "includePostDetails": True,
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/instagram-hashtag-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "hashtags": [
    "travel"
  ],
  "mediaType": "all",
  "includePostDetails": true,
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapesage/instagram-hashtag-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/instagram-hashtag-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/gwvgb617yXo5grXuJ/builds/E5hirFCWwdE6Na15Q/openapi.json
