Instagram Hashtag Post Search
omnial/instagram-hashtag-scraper
Given one or more hashtags (or keywords, with the keyword-search option enabled), returns each matching post's caption, hashtags, tagged accounts, like/comment counts, media type and dimensions, publish time, and the posting account's own name and username. Multi-photo/video 'Sidecar' posts also return each individual child photo/video's own details. Returns an empty result (with an error reason) for a hashtag no post currently uses.
Price
Up to $0.00471 per result; you pay what the call used
You pay the price shown. If a call turns out to cost more than its quote, you pay the actual price, capped at twice the quote. No monthly minimum. Top-ups start at $5.00.
Data source
Data from Instagram.
Use it
Your AI assistant does the work: it finds this tool, shows you the price first, runs it, and you are charged when the run finishes. There is nothing to set up for this tool in particular.
Connect once and your AI can find and run this tool, and any other it needs.
For developers: the calls your assistant makes
// 1. search: find the tool
omnial_search({ query: "what you need" })
// 2. inspect: price and input schema
omnial_inspect({ tool: "omnial/instagram-hashtag-scraper" })
// 3. learn: read the usage guide at runtime
omnial_learn({ tool: "omnial/instagram-hashtag-scraper" })
// 4. run: price the exact call first, then run it
omnial_execute({ tool: "omnial/instagram-hashtag-scraper", input: { /* see input_schema */ }, dry_run: true })
omnial_execute({ tool: "omnial/instagram-hashtag-scraper", input: { /* ... */ } })
// 5. settle: the call is charged when it finishes, nothing to doNot connected yet? Point your MCP client at https://mcp.eden-engine.com/mcp, then copy a config for your client.
Pricing
Every charge this tool can incur.
| Charge | Price |
|---|---|
Per result Charged for every result returned | $0.00471 |
- Updated
- Oct 27, 2026
Input and output schemas
Input schema
{
"type": "object",
"required": [
"hashtags"
],
"properties": {
"hashtags": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\s*#?[^!?.,:;\\-+=*&%$#@/~^|<>()[\\]{}\"'`]+$"
},
"maxItems": 4,
"minItems": 1,
"description": "Type in or paste the hashtag with or without <code>#</code> symbol.<br><br> ⚠️ Each hashtag is treated as <strong>one single search term</strong>. If you put several words in one line (e.g. <code>travel photography food</code>), they'll be merged into a single hashtag (<code>#travelphotographyfood</code>). To search for terms separately, add each one as its own entry using the <strong>+ Add</strong> button — and use keyword search if you need multi-word phrases. <br><br>🔎 <strong>Searching by keyword?</strong> Add your keywords in this same field, then enable <strong>Scrape with a keyword instead of hashtag</strong> toggle below. You can add as many keywords as you like in one field, space-separated."
},
"resultsType": {
"enum": [
"posts",
"reels",
"stories"
],
"type": "string",
"default": "posts",
"enumTitles": [
"Scrape posts",
"Scrape reels",
" "
],
"description": "Choose whether to scrape posts or reels for the selected hashtags or keywords."
},
"resultsLimit": {
"type": "integer",
"default": 20,
"maximum": 30,
"minimum": 1,
"description": "Set the maximum number of results (reels or posts) you want to scrape. If you set this to <code>5</code>, you will scrape 5 posts for each hashtag or keyword you provide. With this setup, if you decide to add <code>7</code> different hashtags or keywords, you will scrape <code>35</code> posts altogether.<br><br>⚠️ A single call only returns the first page of results for each hashtag or keyword; raising this value beyond that first page's size will not return more posts."
},
"keywordSearch": {
"type": "boolean",
"description": "Enable this option if you want to get posts or reels by a specific keyword instead of a hashtag. Add your keywords to the <strong>Hashtags or keywords</strong> field above. Unlike with hashtags, <b>multiple words are supported as keywords</b>, just add spaces between them. The dataset returned will be slightly different than the one produced by a hashtag search."
}
},
"additionalProperties": false
}Output schema
{
"type": "object",
"required": [
"results"
],
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The post's own Instagram media id."
},
"type": {
"type": "string",
"description": "Observed 'Image' and 'Sidecar' (multi-photo/video carousel)."
},
"error": {
"type": "string",
"description": "Present, instead of the post fields above, on the one item returned for a hashtag/keyword with no matches. Observed value: 'no_items'."
},
"caption": {
"type": "string",
"description": "The post's caption text; an empty string when the post has none."
},
"hashtags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Hashtags parsed from the caption; an empty array when none."
},
"mentions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Other Instagram accounts' usernames tagged/mentioned in the caption text (e.g. '@natgeoindia'); an empty array when none."
},
"shortCode": {
"type": "string",
"description": "The post's short code, e.g. 'Ddd90kLRMaR'. Combine with 'https://www.instagram.com/p/' to build the post's public permalink."
},
"timestamp": {
"type": "string",
"description": "ISO 8601 publish time."
},
"childPosts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"caption": {
"type": "string"
},
"hashtags": {
"type": "array",
"items": {
"type": "string"
}
},
"mentions": {
"type": "array",
"items": {
"type": "string"
}
},
"timestamp": {
"type": "string"
},
"productType": {
"type": "string",
"description": "Observed 'carousel_item' for a child photo/video."
},
"commentsCount": {
"type": "integer",
"minimum": 0
},
"dimensionsWidth": {
"type": "integer",
"minimum": 0
},
"dimensionsHeight": {
"type": "integer",
"minimum": 0
}
},
"additionalProperties": false
},
"description": "For a 'Sidecar' (multi-photo/video carousel) post, one entry per child photo/video; an empty array for every other post type."
},
"likesCount": {
"type": "integer",
"minimum": 0
},
"locationId": {
"type": "string",
"description": "The tagged location's own id. Present only when the post is location-tagged -- ABSENT entirely (not null) otherwise; e.g. absent on 2 of 5 posts and present on the other 3 for a `natgeo` search."
},
"productType": {
"type": "string",
"description": "Instagram's own internal post-format label, e.g. 'feed'."
},
"locationName": {
"type": "string",
"description": "The tagged location's display name; same absence behaviour as locationId."
},
"commentsCount": {
"type": "integer",
"minimum": 0
},
"ownerFullName": {
"type": "string",
"description": "The posting account's own display name."
},
"ownerUsername": {
"type": "string",
"description": "The posting account's own username."
},
"dimensionsWidth": {
"type": "integer",
"minimum": 0
},
"paidPartnership": {
"type": "boolean",
"description": "Whether the post is flagged as a paid partnership/brand collaboration."
},
"dimensionsHeight": {
"type": "integer",
"minimum": 0
},
"errorDescription": {
"type": "string",
"description": "Human-readable pair to `error`, e.g. 'Empty or private data for provided input'."
}
},
"additionalProperties": false
},
"description": "One entry per matching post, up to resultsLimit per hashtag/keyword -- or, for a hashtag/keyword with no matches, one item carrying only `error`/`errorDescription`."
}
},
"description": "Matching posts, wrapped in an object because a run's output is always a JSON object -- the provider's own response is a bare array. Up to resultsLimit entries per hashtag/keyword supplied. A hashtag with no matching posts returns one item carrying only `error`/`errorDescription`, no post fields.",
"additionalProperties": false
}