# Instagram Hashtag Scraper — Hashtag Search, Top & Recent Posts (`lergassy/instagram-hashtag-scraper`) Actor

Scrape posts under any Instagram hashtag: author, caption, hashtags, likes, comments, plays, media links and location. Top posts or most recent, one row per post. No login, no run fee.

- **URL**: https://apify.com/lergassy/instagram-hashtag-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Social media, Marketing, AI
- **Features:** Limited permissions
- **Stats:** 30 total users, 18 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.75 / 1,000 target checkeds

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?

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 Posts Scraper** turns public Instagram profiles, post links or hashtags into a flat table. One row per post or per comment: caption, hashtags and mentions pulled out of it, likes, comments, plays, the media file link, location and the author. No login, no cookies, no Instagram account of yours at risk.

### Three modes, one Actor

| Mode | You give | One row is |
|---|---|---|
| 👤 **Posts of a profile** | handles or profile links | one post |
| 💬 **Comments under a post** | post or reel links | one comment |
| #️⃣ **Posts under a hashtag** | hashtags | one post |

Leave **What to collect** empty and the Actor does what its name says: Instagram Posts Scraper collects profile posts, Instagram Comments Scraper collects comments, Instagram Hashtag Scraper collects hashtag posts. Video posts carry their play count and duration.

#### About hashtag order, as of 10 November 2026

Instagram stopped serving the two tabs a hashtag page used to have. There is now **one hashtag feed, ranked by relevance** — the old "Recent" tab is gone and has no replacement. Pick **Most recent** and we sort the posts that feed returned newest first, and put a free note row in the dataset saying so. We do not relabel a relevance ranking as a date ranking.

### Why this needs us at all

Instagram shows none of this to a logged-out visitor: the profile page answers with a redirect to the login screen and its internal API answers `401 require_login`. Checked on 28 October 2026 from a plain server and again through a residential address — same answer both times. This Actor reads the data through a paid source that holds the sessions, so you never hand over your own cookies and never get an account flagged.

### What it costs

Two charges, both stated before you press Start:

| What is charged | When |
|---|---|
| **One target** | Once per profile or post link in your list — even if it turns out to be private, empty or deleted. A hashtag is charged only when it returns posts |
| **One row** | For every post or comment actually delivered |

There is also a **run fee**, and it is the smallest one in this niche — 30% below the cheapest competitor charges to start a run.

#### On the Apify Free plan

A run collects the **first target in your list in full** — every row it has, not a sample — and **nothing is charged at all**. The remaining targets come back as a free note saying they were left alone. So you can see the real shape and the real volume of the data before you pay anything.

The reason the rest is held back is plain: every target costs us a request to a paid data source, and the free plan does not cover it.

Why a target is charged even when it is empty: looking it up costs us one request to the data source whether it returns sixty posts or none. A private profile and a post with comments turned off are normal answers, not failures.

### Output

```json
{
  "type": "post",
  "postUrl": "https://www.instagram.com/p/ABC123/",
  "ownerUsername": "natgeo",
  "takenAt": "2026-10-27T14:07:48.000Z",
  "caption": "…",
  "hashtags": ["wildlife", "photography"],
  "mentions": ["natgeotravel"],
  "likeCount": 27400,
  "commentCount": 312,
  "playCount": 905718,
  "imageUrl": "https://…",
  "videoUrl": null,
  "locationName": "Serengeti"
}
```

Comment rows carry the comment text, its author, when it was written, how many likes and replies it has, and whether the author of the post wrote it.

### What it does not do

- Private accounts. The target is charged like any other lookup, no rows come back.
- Likes of a private post, or who viewed a story. Instagram does not publish those.
- Posting, liking or replying. This Actor only reads.

### For AI agents

- **Minimal input:** `{"mode": "posts", "usernames": ["natgeo"]}` — or `{"mode": "comments", "postUrls": ["https://www.instagram.com/p/DemLxMGgoL_/"]}`, or `{"mode": "hashtags", "hashtags": ["wildlife"]}`.
- **Returns:** one row per post (`posts`, `hashtags`) or per comment (`comments`); `maxItemsPerTarget` caps each profile, post or hashtag. A target that gives nothing — private account, comments off, hidden hashtag — gets one free `type: "notice"` row with the reason, also when other targets in the same run returned rows; filter it out with `type != "notice"`.
- **Time:** about 10 seconds for 20 comments of one post, 30–50 seconds for 60 posts of one profile. A few targets — call synchronously (`run-sync-get-dataset-items`); long lists — start the run and poll it.

### Errors and empty runs

An empty run always says why in its own words — private account, comments turned off, hashtag hidden — in a free `notice` row. Filter it out with `type != "notice"`. If the data source stops answering, the run passes its answer through word for word instead of guessing.

### Your feedback

Found a bug or a missing field? Open an issue on the Actor page. Problems reported by buyers are fixed the same day.

# Changelog

This Actor's version history is a separate document: https://apify.com/lergassy/instagram-hashtag-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Leave empty and the Actor does what its name says: Instagram Posts Scraper collects profile posts, Instagram Comments Scraper collects comments, Instagram Hashtag Scraper collects hashtag posts. Pick a mode only to switch — each mode reads its own field below.

## `usernames` (type: `array`):

Handles (nasa), @handles or profile links. <b>Each profile here is charged once as a target</b>, even if it turns out to be private or empty; delivered posts are charged on top.

## `postUrls` (type: `array`):

Links to posts or reels. <b>Each link here is charged once as a target</b>, even if comments are turned off; delivered comments are charged on top.

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

With or without the # sign. <b>Each hashtag that returns posts is charged once as a target</b>; delivered posts are charged on top. A hashtag our data source has nothing for is not charged and is named in a free note row.

## `hashtagSort` (type: `string`):

Only used in the "hashtags" mode. Instagram stopped serving the separate Top and Recent tabs on 10 November 2026 — there is now one hashtag feed, ranked by relevance. Pick <b>Most recent</b> and we sort the posts that feed returned newest first, and say so in a free note row; it is not the same thing as the old Recent tab, and we will not pretend it is.

## `maxItemsPerTarget` (type: `integer`):

Per profile, per post or per hashtag. The Actor pages until it has this many or the source runs out. <b>On the Apify Free plan a run collects the first target in full and is not charged</b>; the rest of the list comes back as a note.

## Actor input object example

```json
{
  "usernames": [
    "natgeo"
  ],
  "postUrls": [
    "https://www.instagram.com/p/De_qHkUF186/"
  ],
  "hashtags": [
    "travel"
  ],
  "hashtagSort": "top",
  "maxItemsPerTarget": 60
}
```

# Actor output Schema

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

One row per post or per comment.

## `summary` (type: `string`):

Rows delivered, targets charged and how many requests the data source has left.

# 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 = {
    "usernames": [
        "natgeo"
    ],
    "postUrls": [
        "https://www.instagram.com/p/De_qHkUF186/"
    ],
    "hashtags": [
        "travel"
    ],
    "hashtagSort": "top"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/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 = {
    "usernames": ["natgeo"],
    "postUrls": ["https://www.instagram.com/p/De_qHkUF186/"],
    "hashtags": ["travel"],
    "hashtagSort": "top",
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/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 '{
  "usernames": [
    "natgeo"
  ],
  "postUrls": [
    "https://www.instagram.com/p/De_qHkUF186/"
  ],
  "hashtags": [
    "travel"
  ],
  "hashtagSort": "top"
}' |
apify call lergassy/instagram-hashtag-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/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/CCcC7JNFj3OzC6U8d/builds/4lIWdYTnK9auURDPU/openapi.json
