# Instagram Hashtag Scraper · Top Posts & Reels · No Login (`memo23/instagram-hashtag-scraper`) Actor

Scrape any Instagram hashtag — top posts and reels with captions, like and comment counts, play counts, video and thumbnail URLs, creator handle, and tagged accounts. No login, no cookies, no account risk. Many hashtags per run, automatically deduplicated across pages. JSON, CSV, or Excel.

- **URL**: https://apify.com/memo23/instagram-hashtag-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, AI, Automation
- **Stats:** 15 total users, 15 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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.
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 Hashtag Scraper

Turn any Instagram hashtag into a structured stream of posts and reels.
Paste a tag like `coffee`, `#latteart`, or a full explore URL and get captions, engagement counts, play counts, video URLs, and creator handles — no login, no cookies, no account risk.

***

### Why Use This Scraper?

- Top posts and Reels from any public hashtag, in one run
- Real engagement data — likes, comments, and play counts per post
- Direct video and thumbnail URLs, plus the creator's handle and profile picture
- Automatic deduplication — Instagram serves overlapping pages, this actor does not bill you twice for the same post
- Many hashtags per run, processed in parallel
- Flattened rows that drop straight into CSV, Excel, or a spreadsheet
- No login, no cookies, no session tokens — nothing to get your account flagged

***

### Overview

The Instagram Hashtag Scraper is built for social media managers, trend researchers, brand teams, and agencies who need structured post-level data from Instagram hashtags.

The output is **post-shaped rows**. Each row is one Instagram post or reel, tagged with the hashtag it was found under. If you scrape three hashtags, you get one flat dataset containing all posts from all three, each row carrying its own `hashtag` value so you can filter or pivot by tag.

A post genuinely tagged with two of your hashtags appears once per hashtag, because the row is scoped to the tag it was discovered under. Within a single hashtag, every post is unique.

***

### Supported Inputs

#### Input types

| Input type | Pattern | Example |
|---|---|---|
| Bare tag name | `word` | `coffee` |
| Hash-prefixed tag | `#word` | `#latteart` |
| Explore URL | `instagram.com/explore/tags/<tag>/` | `https://www.instagram.com/explore/tags/espresso/` |

All three forms can be mixed in the same run. Tags are case-insensitive and are normalised to lowercase. Unicode tags (`#café`, `#日本`) are supported.

#### Copy-pasteable input

```json
{
  "hashtags": ["coffee", "#latteart", "https://www.instagram.com/explore/tags/espresso/"],
  "resultsType": "both",
  "maxPostsPerHashtag": 100
}
```

#### Unsupported inputs

- **Profile URLs, post URLs, reel URLs** — this actor takes hashtags only
- **Private or restricted tags** — Instagram serves nothing publicly for these
- **"Recent" / chronological posts** — Instagram no longer serves a public recent feed for hashtags. This actor deliberately offers Top and Reels only rather than shipping a mode that returns nothing. See the FAQ.

***

### Use Cases

| Audience | What they use it for |
|---|---|
| Social media managers | Track which posts win on a branded or campaign hashtag |
| Trend researchers | Measure hashtag volume, format mix, and engagement over time |
| Brand teams | Monitor user-generated content and find brand mentions |
| Influencer agencies | Discover creators already posting in a niche, ranked by real engagement |
| Content strategists | Study the top-performing captions, formats, and reel lengths in a topic |
| Market researchers | Compare engagement across competing hashtags or product categories |

***

### How It Works

![How the Instagram Hashtag Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-instagram-hashtag.png)

1. **Normalise the input** — bare names, `#tags`, and explore URLs all resolve to a clean tag name. Invalid input becomes an error row instead of a wasted request.
2. **Look up the hashtag** — confirms the tag exists and reports its total post count on Instagram. A missing tag returns a clear error row.
3. **Page the ranked lists** — Top posts and/or Reels are fetched page by page.
4. **Deduplicate** — Instagram's Top and Reels lists are live ranked sets whose pages overlap heavily. Every post is deduplicated by ID, so you are never charged twice for the same post, and paging stops as soon as the list stops producing anything new.
5. **Push flat rows** — each post becomes one dataset row, ready for export.

***

### Input Configuration

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `hashtags` | array | Yes | — | Hashtags to scrape. Bare names, `#tags`, or explore URLs. |
| `resultsType` | string | No | `top` | `top`, `reels`, or `both`. |
| `maxPostsPerHashtag` | integer | No | unlimited | Cap on posts collected per hashtag. |
| `onlyVideos` | boolean | No | `false` | Skip photo posts, return videos and reels only. |

When `resultsType` is `both`, `maxPostsPerHashtag` is split evenly across the two lists, so a cap of 50 returns roughly 25 top posts and 25 reels rather than 50 top posts and nothing else.

#### Example — top posts only, capped

```json
{
  "hashtags": ["coffee"],
  "resultsType": "top",
  "maxPostsPerHashtag": 50
}
```

#### Example — reels only, for video trend research

```json
{
  "hashtags": ["latteart", "espresso", "coldbrew"],
  "resultsType": "reels",
  "maxPostsPerHashtag": 100,
  "onlyVideos": true
}
```

***

### Output Overview

One dataset row per post. Every row identifies the hashtag it came from and which list it was found in (`top` or `reels`), then carries the post itself: identifiers and URL, media type, timestamp, caption, engagement counts, video metadata, and the creator's public profile fields.

Rows for hashtags that could not be scraped are returned as error rows carrying `hashtag`, `error`, and `message` — these are never charged.

***

### Output Samples

Real row, produced from `hashtags: ["latteart"]` with `resultsType: "both"` (CDN URLs shortened):

```json
{
  "hashtag": "latteart",
  "resultsType": "top",
  "postId": "3950574492081015707",
  "shortCode": "DbTQpHLNUub",
  "postUrl": "https://www.instagram.com/p/DbTQpHLNUub/",
  "mediaType": "video",
  "productType": "clips",
  "takenAt": "2026-07-27T15:13:56Z",
  "caption": "#barista #home #coffee #latteart #kaffee",
  "likeCount": 16,
  "commentCount": 3,
  "playCount": 258,
  "videoDuration": 13.418999671936035,
  "isPaidPartnership": false,
  "ownerUsername": "baris_tant",
  "ownerFullName": "Baristant",
  "ownerId": "14523707386",
  "ownerProfilePicUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.82787-19/...",
  "thumbnailUrl": "https://scontent-lga3-1.cdninstagram.com/v/t51.82787-15/...",
  "videoUrl": "https://scontent-lga3-1.cdninstagram.com/o1/v/t2/f2/m86/...",
  "locationName": null,
  "taggedUsernames": []
}
```

Error row for a tag that does not exist:

```json
{
  "hashtag": "thistagdoesnotexistatall",
  "error": "hashtag_not_found",
  "message": "Hashtag #thistagdoesnotexistatall was not found on Instagram."
}
```

***

### Key Output Fields

**Source**
`hashtag`, `resultsType`

**Post identity**
`postId`, `shortCode`, `postUrl`, `mediaType`, `productType`, `takenAt`

**Content**
`caption`, `taggedUsernames`, `locationName`, `isPaidPartnership`

**Engagement**
`likeCount`, `commentCount`, `playCount`

**Media**
`thumbnailUrl`, `videoUrl`, `videoDuration`

**Creator**
`ownerUsername`, `ownerFullName`, `ownerId`, `ownerProfilePicUrl`

***

### FAQ

**Can I get recent / chronological posts for a hashtag?**
No, and no actor can reliably. Instagram stopped serving a public chronological hashtag feed — the underlying endpoint returns an empty page for every tag. Rather than ship a "Recent" option that silently returns nothing, this actor offers Top and Reels only.

**How many posts can I get per hashtag?**
Instagram's Top and Reels lists are ranked sets of limited depth, not full archives. Expect a few hundred posts per hashtag in practice. Setting `maxPostsPerHashtag` to 10,000 will not produce 10,000 rows — paging stops once the list stops returning new posts.

**Why do I sometimes get fewer posts than I asked for?**
Either the hashtag's ranked list ran out, or `onlyVideos` filtered out photo posts. Both are logged.

**Is the same post ever returned twice?**
Not within a hashtag. Instagram's pages overlap heavily and the actor deduplicates by post ID, so you are never billed twice for the same post. A post tagged with two of your hashtags does appear once under each, because each row is scoped to its tag.

**Does it return comments or the list of likers?**
No. This actor returns post-level data including comment and like *counts*. For comment text see the Instagram Comments Scraper, and for the people who liked a post see the Instagram Post Likers Scraper.

**Do I need an Instagram account, login, or cookies?**
No. Nothing is authenticated and no session is used, so there is no account to get flagged.

**What happens with a private or restricted hashtag?**
You get an error row explaining it, and you are not charged for it.

***

### Support

Found a bug or need a field that is not there? Open an issue on the actor's **Issues** tab and it will be looked at.

Email: muhamed.didovic@gmail.com

***

### Additional Services

Need a custom scraper, a tailored export format, or an integration into your own pipeline? Custom builds are available — get in touch at muhamed.didovic@gmail.com.

***

### Explore More Scrapers

- **Instagram Profile Scraper** — profiles, posts and comments from any public account
- **Instagram Stories & Highlights Scraper** — active stories and permanent highlights
- **Instagram Followers & Following Scraper** — full follower and following lists
- **Instagram Post Likers Scraper** — who liked any public post or reel
- **Instagram Comments Scraper** — full comment threads with replies
- **Instagram Similar Profiles & Lookalike Finder** — accounts similar to any profile
- **Instagram Reels Search & Viral Finder** — find trending reels by keyword

Browse the full collection at [apify.com/memo23](https://apify.com/memo23).

***

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/instagram-hashtag-scraper`).

**Purpose:** Scrapes public Instagram hashtags into post-level rows (Top posts and/or Reels), with automatic cross-page deduplication.

**Minimal input:**

```json
{ "hashtags": ["coffee"], "resultsType": "top", "maxPostsPerHashtag": 20 }
```

**Output:** one dataset row per post — hashtag, resultsType, postId, shortCode, postUrl, mediaType, productType, takenAt, caption, likeCount, commentCount, playCount, videoDuration, isPaidPartnership, ownerUsername, ownerFullName, ownerId, ownerProfilePicUrl, thumbnailUrl, videoUrl, locationName, taggedUsernames. Failed hashtags return `{hashtag, error, message}` instead.

**Behaviors an agent should know:**

- Always set `maxPostsPerHashtag`. Uncapped runs page until Instagram stops returning new posts.
- Instagram's ranked lists are shallow — expect a few hundred posts per tag, not thousands, regardless of the cap.
- With `resultsType: "both"` the cap is split evenly between Top and Reels.
- There is no "recent" mode; Instagram's public chronological hashtag feed returns nothing, so only `top`, `reels`, and `both` exist.
- Billing: one `post` event per post row delivered. Error rows are never charged. Duplicate posts within a hashtag are deduplicated before billing.
- No login is used, so no authenticated-only fields (viewer state, private accounts) are available.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc. or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available Instagram hashtag pages — no authenticated endpoints, paid features, or content behind the instagram.com login wall. Users are responsible for ensuring their use complies with instagram.com's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

***

### SEO Keywords

instagram hashtag scraper, scrape instagram hashtag, instagram hashtag API, instagram.com scraper, Apify instagram, hashtag posts scraper, instagram reels scraper, instagram top posts scraper, social media scraper, hashtag analytics data, instagram engagement data, instagram trend research, user generated content scraper, influencer discovery data, instagram content strategy, brand monitoring scraper, social listening data, instagram marketing intelligence, no login instagram scraper

# Actor input Schema

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

Instagram hashtags to scrape. Accepts bare names (coffee), #-prefixed tags (#coffee), or explore URLs (https://www.instagram.com/explore/tags/coffee/) — one per line, mixed formats are fine. Non-existent tags return an error item.

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

Top posts (Instagram's ranked best-performing posts for the tag), Reels (short videos tagged with it), or both. A post that appears in both lists is returned — and charged — only once.

## `maxPostsPerHashtag` (type: `integer`):

Cap how many posts to collect per hashtag. Leave empty for as many as Instagram will serve. Note Instagram's top/reels lists are live ranked sets of limited depth — very large numbers will stop early once the list stops returning new posts.

## `onlyVideos` (type: `boolean`):

Skip photo posts and return only videos and reels. Applies to both result types. Default: off.

## Actor input object example

```json
{
  "hashtags": [
    "coffee",
    "#latteart",
    "https://www.instagram.com/explore/tags/espresso/"
  ],
  "resultsType": "top",
  "maxPostsPerHashtag": 100,
  "onlyVideos": false
}
```

# 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": [
        "coffee"
    ],
    "maxPostsPerHashtag": 100
};

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

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

```

## MCP server setup

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

```

## OpenAPI specification

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