# Instagram Hashtag Scraper — Fast Posts, Reels & Metrics (`subimpact/instagram-hashtag-scraper`) Actor

Native Instagram hashtag & explore scraper. Extract reels, posts, captions, view counts, likes, comments, and creators at an ultra-competitive price.

- **URL**: https://apify.com/subimpact/instagram-hashtag-scraper.md
- **Developed by:** [subimpact](https://apify.com/subimpact) (community)
- **Stats:** 4 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 posts

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Instagram Hashtag Scraper 📸

A high-performance, native Instagram hashtag scraper engineered for reliability, deep data fidelity, and ultra-competitive pricing.

> **1:1 Drop-in Replacement for `apify/instagram-hashtag-scraper`** at **$0.0010/result**, below Apify's $0.0026 Free-plan list price.

***

### ⚡ Features & Advantages

- **Zero Upstream Dependencies:** Powered by native browser extraction with stealth headers and proxy rotation. No 3rd-party actor delegation or hidden markups.
- **Full Apify Schema Compatibility:** Drop-in replacement for existing workflows, pipelines, and integrations.
- **Pay-Per-Event Monetization:** Only pay for the posts and reels you actually scrape ($0.0010 per post).
- **Rich Data Extraction:**
  - Post metadata (ID, shortCode, URL, post type, captions, timestamps)
  - Creator insights (ownerUsername, ownerId)
  - Engagement metrics (likesCount, commentsCount, videoPlayCount, videoViewCount)
  - Media assets (high-res displayUrl, direct videoUrl, alt accessibility text)
  - Parsed hashtags and user mentions

***

### 💰 Pricing

$0.0010 per delivered result ($1.00 per 1,000 posts), plus a $0.00005 actor-start event. You are charged only for posts and reels that reach the dataset.

### How this compares

The output schema matches `apify/instagram-hashtag-scraper`, so an existing pipeline swaps over without reshaping. At $1.00 per 1,000 posts it is below `apify/instagram-hashtag-scraper` ($2.60) and `apify/instagram-hashtag-analytics-scraper` ($2.30, plus a $0.001 start event per run and $0.007 per top-posts or latest-posts call). apidojo/instagram-hashtag-scraper lists $0.40 per 1,000 dataset items but charges $0.016 per keyword query on top, and scraping_solutions/instagram-hashtag-scraper-pro-no-cookies lists $1.25.

| Actor | Price per 1,000 posts | Platform usage |
|---|---|---|
| subimpact/instagram-hashtag-scraper | $1.00 | not billed separately |
| apify/instagram-hashtag-scraper | $2.60 | see listing |
| apify/instagram-hashtag-analytics-scraper | $2.30 | see listing |
| apidojo/instagram-hashtag-scraper | $0.40 plus $16.00 per keyword query | see listing |
| scraping_solutions/instagram-hashtag-scraper-pro-no-cookies | $1.25 | see listing |

Prices are Apify Store list prices on the Free plan, checked 24 October 2026. Competitor prices can change; check their listings.

***

### 📥 Input Parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `hashtags` | Array of Strings | **Yes** | `["malaysianfood"]` | List of Instagram hashtags to scrape (with or without `#`). Runs are capped at the first 20 hashtags. |
| `resultsLimit` | Integer | No | `20` | Max posts or reels to extract per hashtag (1–1000). |
| `resultsType` | Enum | No | `posts` | `posts` or `reels` — which content type to scrape. When `reels` is requested, photo posts are never returned. |
| `keywordSearch` | Boolean | No | `false` | Treat search terms as keyword phrases instead of single hashtags. Keyword search requires a logged-in session (`sessionCookie`): logged-out keyword terms hit Instagram's login wall, so the run stops after 2 consecutive walled terms and pushes one clear, un-charged error row per remaining term instead of retrying for hours. |
| `dryRun` | Boolean | No | `false` | Run input validation without extracting live posts or triggering billing. |
| `proxyConfiguration` | Object | No | `{ "useApifyProxy": true }` | Apify Proxy configuration. **Note:** with the default options (no groups) the run uses Apify **datacenter** IPs, which Instagram heavily blocks. Enable the `RESIDENTIAL` proxy group — or supply `sessionCookie`, which uses its own residential lane — for reliable extraction. |
| `sessionCookie` | String | No | empty | Optional sessionid cookie for logged-in mode. Used for this run only, never stored or logged. |
| `feedType` | Enum | No | `top` | Logged-in mode only: `top` (ranked grid) or `recent` (newest posts first). |

***

### 🆘 When a run delivers 0 posts

Instagram blocks most datacenter IP ranges outright, so the default proxy options (Apify datacenter proxies, no session cookie) often yield 0 results for the logged-out lane. When that happens, the run is deliberately marked **failed** (never a silent success) with a status message that names the fix:

- enable the `RESIDENTIAL` proxy group in the `proxyConfiguration` input, or
- supply a `sessionCookie` — the logged-in lane runs through its own sticky residential proxy.

Nothing is charged for the blocked run's placeholder/error rows.

***

### 🔐 Logged-in mode

Logged out, Instagram caps a hashtag at roughly 12 posts and hides play counts. With a session cookie, this actor calls the Instagram hashtag API directly instead and returns the full feed: up to `resultsLimit` posts per hashtag (hard cap 1,000), real `videoPlayCount` for reels, and a choice of feed.

- **Bring your own cookie (optional):** paste the `sessionCookie` input, either a raw `Cookie: ...` header string or just the `sessionid` value. Credentials are used only to call Instagram from within the run and are never stored, logged, or included in the dataset.
- **Owner deployments:** cookies can also be supplied through the `IG_SESSION_COOKIES` environment variable as a JSON object. An input cookie takes precedence over the env var.
- **Feed types:** `top` returns the ranked grid the hashtag page shows by default; `recent` returns the newest posts first. Both paginate automatically with polite 1.5-3.5 s delays between page requests, capped at 40 pages per hashtag.
- **Graceful fallback, with a wall guard:** if Instagram rejects the session (login wall, challenge, rate limit), the run logs a warning and automatically continues with the logged-out mode for the remaining hashtags. Logged-out keyword search is not available, so after 2 consecutive keyword terms hit the wall the run stops trying them (one un-charged `login_wall` error row per remaining term, no browser work) and the status message summarises delivered vs walled/skipped terms. Every term is also capped by a per-term time budget. The run summary (KV `OUTPUT`) reports `authMode`, `sessionStatus` (`ok`, `invalid`, or `not_provided`) and the walled/skipped terms.
- **Account risk:** use a secondary throwaway account, never your main one. Automated API calls from a shared hosting IP range may violate Instagram's terms and can lead to account restrictions. Rows produced by logged-in mode are marked `enrichmentSource: "session"` in the dataset.

***

### 📤 Output Dataset Format

Every post pushed to the default dataset follows the standard schema:

```json
{
  "id": "3350192837482910293",
  "type": "Image",
  "shortCode": "C7AB123xyZ",
  "caption": "Delicious artisan coffee in Tokyo #tokyocafe #coffeelover Photo by @tokyobarista",
  "hashtags": ["tokyocafe", "coffeelover"],
  "mentions": ["tokyobarista"],
  "url": "https://www.instagram.com/p/C7AB123xyZ/",
  "commentsCount": 128,
  "displayUrl": "https://scontent.cdninstagram.com/v/t51/sample.jpg",
  "alt": "Delicious artisan coffee in Tokyo #tokyocafe #coffeelover Photo by @tokyobarista",
  "likesCount": 3420,
  "timestamp": "2026-05-01T12:00:00.000Z",
  "ownerUsername": "tokyobarista",
  "ownerId": "1029384756"
}
```

***

### 🛠️ Local Development & Testing

```bash
npm install
npm test
npm start
```

# Actor input Schema

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

List of Instagram hashtags to scrape (with or without #). Runs are capped at the first 20 hashtags. Defaults to \['malaysianfood'] when not provided.

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

Maximum number of posts or reels to scrape per hashtag.

## `resultsType` (type: `string`):

Choose whether to scrape posts or reels for the selected hashtags.

## `keywordSearch` (type: `boolean`):

Treat search terms as keyword phrases instead of single hashtags.

## `dryRun` (type: `boolean`):

Validates hashtag parameters without extracting live data or triggering billing charges.

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

Apify Proxy configuration. WARNING: with the default options (no groups) the run uses Apify datacenter IPs, which Instagram blocks. Enable the RESIDENTIAL proxy group (or supply a sessionCookie, which uses its own residential lane) for reliable extraction.

## `sessionCookie` (type: `string`):

OPTIONAL. Paste a sessionid cookie from a secondary Instagram account (never your main account; using an account may violate Instagram terms and risk restrictions). Accepted forms: a raw Cookie header string (e.g. 'sessionid=...; ds_user_id=...'), just the sessionid value, or 'sessionid=<value>'. The cookie is used only to call the Instagram API from within this run to bypass the logged-out ~12-post cap and to unlock play counts; it is never stored in the dataset, logged, or persisted anywhere. Leave empty to scrape logged out.

## `feedType` (type: `string`):

Which hashtag feed to fetch in logged-in mode: the ranked Top grid (default) or the newest posts first (Recent). Logged-out mode always returns the ranked grid.

## Actor input object example

```json
{
  "hashtags": [
    "malaysianfood",
    "klfoodie"
  ],
  "resultsLimit": 20,
  "resultsType": "posts",
  "keywordSearch": false,
  "dryRun": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "feedType": "top"
}
```

# Actor output Schema

## `results` (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 = {
    "hashtags": [
        "malaysianfood"
    ],
    "resultsLimit": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("subimpact/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": ["malaysianfood"],
    "resultsLimit": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("subimpact/instagram-hashtag-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 '{
  "hashtags": [
    "malaysianfood"
  ],
  "resultsLimit": 20
}' |
apify call subimpact/instagram-hashtag-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,subimpact/instagram-hashtag-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/P4GZr0id4sNUTji1M/builds/z5TFCzOaE8i6c5frK/openapi.json
