Instagram Hashtag Scraper & Instagram Reels Search, No Login
Pricing
from $1.35 / 1,000 reels
Instagram Hashtag Scraper & Instagram Reels Search, No Login
Scrape Instagram hashtags and keywords: an Instagram keyword search and hashtag scraper for the top reels of any hashtag or keyword. Per reel the caption, exact time, plays, likes, comments, owner and full name, music, location, tags and video URLs; per hashtag its post count and related keywords.
Pricing
from $1.35 / 1,000 reels
Rating
0.0
(0)
Developer
Hyperbach
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
Instagram's top reels for any hashtag or keyword, as data, logged out. Give hashtags (natgeo, #natgeo, a hashtag link) or search keywords (skincare routine) and get Instagram's own ranked list of reels for each, in its order, to the list's end — each reel with its whole caption and its hashtags and mentions, the exact publish time, the plays, the likes (null when the owner hides them, never a fake number), the comment count, the duration, the owner with their full name, the music title and artist, the location, the tagged accounts, the coauthors, the latest comments, Instagram's topic tags and alt text, and the video, cover and audio URLs with the time they expire. Every hashtag or keyword also gets a free search row: the hashtag's post count, Instagram's related keywords and its description of the term, how many reels the list held and a verdict (COMPLETE: the list ended; CAPPED: your limit came first). No login, no Instagram account, no cookie, proxies handled for you.
Why this Instagram hashtag scraper
- Instagram's own top list, to its end. Instagram ranks about 50 to 70 reels for a hashtag or keyword (natgeo 59, nature 53, six ordinary keywords 58 to 70 on our runs). This Actor reads the list to Instagram's own end flag and says so on the search row (
COMPLETE, with the list's length); a shorter dataset is never silent. Each row has itsrank, 1 = the top. - The fields other hashtag scrapers leave out. The owner's full name and the music title and artist come from each reel's own record, read for every reel by default: on natgeo's 59 reels, 59 owner names, the music on all 54 that carry a sound asset, 38 locations, the latest comments on all 59. Turn
includeDetailsoff for a faster run with the lists' fields only. - Counts that do not lie. A reel whose owner hides its likes gets
likesnull andlikes_hiddentrue; Instagram serves a placeholder number for those, and some scrapers deliver it or -1 as the count. The plays are Instagram's own counter from the ranked list, not Facebook's and not the smaller embed counter (that one isviews, on request). - The hashtag's figures for free. Each input's search row carries the hashtag's post count as Instagram shows it (natgeo 27,862,149; a phrase's joined hashtag, e.g.
skincareroutine38.8 M), Instagram's related keywords (up to 48), its own description of the term, and the averages and top creators over the reels delivered. - Hashtags typed any way.
#NatGeo,natgeo, a hashtag link and a popular-page link are one term: Instagram's list is case-sensitive, so the term is lower-cased; accents and other scripts are kept (ラーメンworks;caféandcafeare two terms). A term Instagram does not know is a free row that says so, after a second connection agrees. - One row per reel, free rows for the rest. A reel listed under two of your hashtags is one row and one charge. A reel a filter leaves out, one
onlyNewReelsalready delivered, an input with no list: free.maxReelsPerInputgives exactly that many when the list holds them. - Plain HTTP, no browser. Instagram's own logged-out answers: no login, no cookie, no account of yours, nothing to configure. On our test from a laptop the first row came 3.6 seconds after the start and two hashtags' 112 reels with every detail in 26 seconds.
Who it's for
- Marketers and brand teams — the reels that rank for a campaign hashtag or a product keyword right now, with their plays, likes, comments, music and creators, and the hashtag's size, on a schedule with only the new reels.
- Influencer and creator scouts — the creators who rank for a niche's hashtags and keywords, with their full names, verified flags and, on request, their follower counts and engagement per follower.
- Trend and music researchers — which sounds, topics and captions rank for a term, across related keywords in one run, with the exact publish times.
- Developers and data teams — typed rows keyed by the media id with Instagram's rank, one free search row per input, a run summary to check a pipeline against.
Quick start
A hashtag's top 20 reels
{"hashtags": ["natgeo"],"maxReelsPerInput": 20}
Several keywords to the end of their lists
{"keywords": ["skincare routine","street food bangkok"],"maxReelsPerInput": 100}
A hashtag and its related keywords, the last 30 days only
{"hashtags": ["sourdough"],"maxReelsPerInput": 50,"relatedKeywordsDepth": 3,"newerThan": "30 days"}
A fast light run: the lists' fields only
{"hashtags": ["natgeo","nature"],"maxReelsPerInput": 100,"includeDetails": false}
Only the new top reels since the last run (for a schedule)
{"hashtags": ["natgeo"],"maxReelsPerInput": 50,"onlyNewReels": true,"stateStoreName": "natgeo-daily"}
Output
One row per reel (and one free search row per hashtag or keyword):
| field | meaning |
|---|---|
record_type | reel (a reel of a ranked list: charged when status is ok) or search (a free row per hashtag or keyword: the hashtag's figures and what the walk read, or why the input gave no reel). |
status | A reel: ok. A search row: ok (see verdict), no_ranked_list (Instagram knows the term — its description is in description — and shows no ranked reels list for it; two exits agree), unknown_term (Instagram does not know the term as typed; two exits agree: try another spelling), invalid_input (the value names no hashtag or keyword), failed, not_read (maxItems, the charge limit or the time limit came first). |
input | The value you gave that led to this row (a related keyword's own text on its rows). |
input_type | hashtag, keyword, related (a related keyword walked with relatedKeywordsDepth) or invalid. |
keyword | The term Instagram's ranked list was read for: your value lower-cased, without # or the link's path. |
related_to | On a related keyword's rows: the input whose related keyword it is. |
rank | The reel's place in Instagram's ranked list for the keyword, 1 = the top. |
id | Instagram's media id (pk) of the reel. One row per id in a run. |
shortcode | The reel's shortcode (instagram.com/reel/<shortcode>/). |
url | The reel's link. |
type | reel for a reel (product_type clips), video for a feed video Instagram puts on a ranked list now and then (product_type feed; it has no plays), carousel for a carousel. Without includeDetails it is read from the list: a reel carries a sound kind, a feed video none. |
product_type | Instagram's own type of the media (clips for a reel), from the reel's record (includeDetails). |
timestamp | The exact publish time (UTC, ISO 8601). |
taken_at | The exact publish time as a Unix timestamp (seconds). |
caption | The caption in full. |
hashtags | The hashtags of the caption, in order, without #. |
mentions | The accounts the caption mentions, without @. |
caption_is_edited | True when the caption was edited after publishing (includeDetails). |
caption_created_at | When the caption's current text was written (UTC; includeDetails). |
alt | Instagram's alt text of the reel (includeDetails). |
likes | The like count; null when the owner hides the likes (likes_hidden true) — never Instagram's placeholder value. |
likes_hidden | True when the owner hid the like and view counts. |
comments_count | The comment count. |
plays | The play count Instagram's ranked list shows; null on the list's last 1–11 reels, which Instagram serves without plays (plays_status). |
plays_status | served, not_in_ranked_head (one of the list's last reels, which Instagram serves without a play count) or not_served. |
views | The view counter of the reel's embed page (includeViews; a quarter to a half of the plays): null when Instagram hides the counts or the reel's embed page carries no record (2 of 16 reels with visible counts on our test). |
video_duration | The video's length in seconds. |
has_audio | False for a reel with no sound track. |
engagement_per_play | (likes + comments) ÷ plays, four significant digits; null when the likes are hidden or there are no plays. |
engagement_rate | (likes + comments) ÷ the owner's followers (includeOwnerFollowers); null without the followers or with hidden likes. |
owner_username | The reel's owner's username. |
owner_id | The owner's account id (pk). |
owner_full_name | The owner's full name as their profile shows it (includeDetails; null when the profile has none). |
owner_is_verified | True when the owner's account is verified. |
owner_profile_pic_url | The owner's profile picture (a signed URL). |
owner_followers | The owner's follower count (includeOwnerFollowers). |
coauthors | The coauthors of a collab reel: {username, id, is_verified, full_name, profile_pic_url} (includeDetails). |
tagged_users | The accounts tagged in the reel: {username, full_name, id, is_verified, profile_pic_url} (includeDetails). |
location_name | The reel's location name (includeDetails; null when it has none). |
location_id | Instagram's id of the location. |
location_lat | The location's latitude. |
location_lng | The location's longitude. |
display_url | The reel's cover image (a signed URL, see media_urls_expire_at). |
video_url | The reel's video file (a signed URL). |
audio_url | The reel's audio-only track (HE-AAC; a signed URL); null when the reel has no sound. |
media_urls_expire_at | When the row's signed media URLs stop working (UTC; 1 to 4 days after the read). |
width | The video's width in pixels. |
height | The video's height in pixels. |
sound_type | original (the creator's own audio), licensed (a track from Instagram's music library) or none. |
audio_muted | Instagram's own mute flag of the reel's sound: true when it serves the reel without its music track, with the reason in audio_muted_reason ("This song is currently unavailable."; the reason comes with includeDetails, the list gives the flag only); false when the sound is not muted or the reel has no sound asset. Every reel is read from an exit whose sound is checked first: a few exits serve every licensed track muted or as the creator's original audio, and the actor moves off them before it reads a reel there. |
audio_muted_reason | Instagram's reason for a muted sound, as it gives it; null when the sound is not muted. |
music | The sound: {title, artist, audio_id, uses_original_audio} (includeDetails); a licensed track Instagram marks unavailable has its title and artist null. |
music_trending | True when Instagram marks the sound as trending in reels (includeDetails). |
ai_label | Instagram's own AI label of the reel; null when it shows none (includeDetails). |
topics | Instagram's own topic tags of the reel (includeDetails). |
latest_comments | The reel's latest comments as Instagram shows them logged out, up to 15: {id, text, timestamp, likes, owner_username, owner_id, owner_is_verified, gif_url} (includeDetails); a comment with no text (a sticker) has text "" and is kept. |
first_comment | The text of the first comment Instagram serves with the reel (includeDetails). |
details_status | served (the reel's own record was read), not_asked (includeDetails off), failed (the record did not answer: the list's fields are there) or not_found. |
post_count | On a search row: the hashtag's post count as Instagram shows it (the hashtag spelled as the keyword without spaces); null when Instagram lists no such hashtag. |
hashtag_id | On a search row: Instagram's id of that hashtag. |
hashtag_name | On a search row: the hashtag the post count belongs to. |
related_keywords | On a search row: Instagram's related keywords for the term (up to relatedKeywordsCount). |
description | On a search row: Instagram's own description of the term, when it shows one. |
verdict | On a search row: COMPLETE (Instagram's ranked list ended: every reel read), CAPPED (maxReelsPerInput), RUN_CAP (maxItems or the charge limit), PARTIAL (an error or the time limit stopped it; the note says which). |
reels_listed | On a search row: the reels of the ranked list the walk read (with COMPLETE, the list's whole length). |
reels_delivered | On a search row: the reels delivered from this input. |
avg_plays | On a search row: the average plays over the reels delivered from this input. |
median_plays | On a search row: the median plays over those reels. |
avg_likes | On a search row: the average likes over those reels (hidden likes left out). |
median_likes | On a search row: the median likes over those reels. |
avg_comments | On a search row: the average comment count over those reels. |
median_comments | On a search row: the median comment count over those reels. |
top_creators | On a search row: the owners with the most reels among those delivered: {username, reels, plays}, up to 5. |
note | Why, in words: the reason of a free row, what a walk did not read and why. |
scraped_at | When the row was read (UTC). |
Example record:
{"record_type": "reel","status": "ok","input": "natgeo","input_type": "hashtag","keyword": "natgeo","related_to": null,"rank": 4,"id": "3992952281495587802","shortcode": "Ddp0PHHoUva","url": "https://www.instagram.com/reel/Ddp0PHHoUva/","type": "reel","product_type": "clips","timestamp": "2026-09-24T02:44:20Z","taken_at": 1790217860,"caption": "राणा — शान भी, सल्तनत भी।🐆👑\n\n@natgeoindia @natgeo @nikonindiaofficial \n\n#reels #trendingreels #reelsinstagram #trending #viralvideos \n.\n.\n.\n.\nRana Leopard | Indian Leopard | Jawai Wildlife | Leopard Photography | Rajasthan Wildlife | Wildlife India | Majestic Leopard | Big Cat | Wildlife Reel","hashtags": ["reels","trendingreels","reelsinstagram","trending","viralvideos"],"mentions": ["natgeoindia","natgeo","nikonindiaofficial"],"caption_is_edited": false,"caption_created_at": "2026-09-24T02:44:09Z","alt": "Video by Dushyant Malhotra| Wildlife Creator on September 23, 2026. May be an image of cheetah, big cat and text.","likes": 37269,"likes_hidden": false,"comments_count": 85,"plays": 876523,"plays_status": "served","views": null,"video_duration": 16.136,"has_audio": true,"engagement_per_play": 0.04262,"engagement_rate": null,"owner_username": "dushyant_wildtrails","owner_id": "3911404912","owner_full_name": "Dushyant Malhotra| Wildlife Creator","owner_is_verified": true,"owner_profile_pic_url": "https://scontent-xxc1-1.cdninstagram.com/v/t51.82787-19/567468550_18393098221132913_4935748518260328495_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=102&ccb=7-5&_nc_sid=f7ccc5&efg=eyJ2ZW5jb2RlX3RhZyI6InByb2ZpbGVfcGljLnd3dy4xMDgwLkMzIn0%3D&_nc_ohc=REDACTED&_nc_oc=REDACTED&_nc_zt=24&_nc_ht=scontent-xxc1-1.cdninstagram.com&_nc_gid=REDACTED&_nc_ss=7ea8c&oh=REDACTED&oe=6ADF4B5D","owner_followers": null,"coauthors": [],"tagged_users": [{"username": "nikonindiaofficial","full_name": "Nikon India Pvt Ltd.","id": null},{"username": "rajasthan_tourism","full_name": "Rajasthan Tourism","id": null},{"username": "rajasthanforestdepartment","full_name": "Rajasthan Forest Department","id": null}],"location_name": "Jhalana Reserve Forest","location_id": "1262395790532175","location_lat": 26.855243742451,"location_lng": 75.833497796402,"display_url": "https://scontent-xxc1-1.cdninstagram.com/v/t51.82787-15/818854974_18445259269132913_8361329682113486626_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=102&ig_cache_key=Mzk5Mjk1MjI4MTQ5NTU4NzgwMjE4NDQ1MjU5MjYzMTMyOTEz.3-ccb7-5&ccb=7-5&_nc_sid=58cdad&efg=eyJ2ZW5jb2RlX3RhZyI6IkNMSVBTLnhwaWRzLjEyMDIuc2RyLnZpZGVvX2RlZmF1bHRfY292ZXJfZnJhbWUuQzMifQ%3D%3D&_nc_ohc=REDACTED&_nc_oc=REDACTED&_nc_zt=23&_nc_ht=scontent-xxc1-1.cdninstagram.com&_nc_gid=REDACTED&_nc_ss=7ea8c&oh=REDACTED&oe=6ADF666A","video_url": "https://scontent-xxc1-1.cdninstagram.com/o1/v/t16/f2/m84/AQN3fkvAohahzn0pNk1KNTt_fS758G2LeysKEZJ11h_V2FUXeWtZSR_OocjsOlPrwkl-X5F5Zl-JIxjBW8FgyLvqOQpvShlNIuCZJeU.mp4?_nc_cat=103&_nc_sid=5e9851&_nc_ht=scontent-xxc1-1.cdninstagram.com&_nc_ohc=REDACTED&efg=eyJ2ZW5jb2RlX3RhZyI6Inhwdl9wcm9ncmVzc2l2ZS5JTlNUQUdSQU0uQ0xJUFMuQzMuNzIwLmRhc2hfYmFzZWxpbmVfMV92MSIsInhwdl9hc3NldF9pZCI6MTE0NDA5NjE2NDYwODQ3NywiYXNzZXRfYWdlX2RheXMiOjI4LCJ2aV91c2VjYXNlX2lkIjoxMDgyNywiZHVyYXRpb25fcyI6MTYsInVybGdlbl9zb3VyY2UiOiJ3d3cifQ%3D%3D&ccb=17-1&vs=87ec90dae2b449ab&_nc_vs=HBksFQIYTGlnX2JhY2tmaWxsX3RpbWVsaW5lX3ZvZC9CNjQ2RDUxODJEQUYyOTBEN0I3RkIyREVEQUJEMUZCMF92aWRlb19kYXNoaW5pdC5tcDQVAALIARIAFQIYUWlnX3hwdl9wbGFjZW1lbnRfcGVybWFuZW50X3YyL0U3NERGQzMxQTQ3NzUyMTlFRkVBODRBQjg0OUJEMjhCX2F1ZGlvX2Rhc2hpbml0Lm1wNBUCAsgBEgAoABgAGwKIB3VzZV9vaWwBMRJwcm9ncmVzc2l2ZV9yZWNpcGUBMRUAACa659fXlKOIBBUCKAJDMywXQDAiDEm6XjUYEmRhc2hfYmFzZWxpbmVfMV92MREAdf4HZZapAQA&_nc_gid=REDACTED&_nc_ss=7ea8c&_nc_zt=28&oh=REDACTED&oe=6ADB60A5","audio_url": "https://scontent-xxc1-1.cdninstagram.com/o1/v/t2/f2/m78/AQPU0MwwtYsRI6FJzgo9vIjurSd_K5eI4UycrHEodsm4wweskVOEwL8a_ysCxj33SsM4tqNQxD8s-c4tZUFHvfvWde8Thk3HjwgfVsQ.mp4?_nc_cat=107&_nc_sid=9ca052&_nc_ht=scontent-xxc1-1.cdninstagram.com&_nc_ohc=REDACTED&efg=eyJ2ZW5jb2RlX3RhZyI6ImlnLXhwdmRzLmNsaXBzLmlnd3d3LUMzLmRhc2hfbG5faGVhYWNfdmJyM19hdWRpbyIsInZpZGVvX2lkIjpudWxsLCJvaWxfdXJsZ2VuX2FwcF9pZCI6OTM2NjE5NzQzMzkyNDU5LCJjbGllbnRfbmFtZSI6ImlnIiwieHB2X2Fzc2V0X2lkIjoxMTQ0MDk2MTY0NjA4NDc3LCJhc3NldF9hZ2VfZGF5cyI6MjgsInZpX3VzZWNhc2VfaWQiOjEwODI3LCJkdXJhdGlvbl9zIjoxNiwiYml0cmF0ZSI6NzMxOTEsInVybGdlbl9zb3VyY2UiOiJ3d3cifQ%3D%3D&ccb=17-1&_nc_gid=REDACTED&_nc_ss=7ea8c&_nc_zt=28&oh=REDACTED&oe=6ADB658C","media_urls_expire_at": "2026-10-23T13:27:01Z","width": 1440,"height": 2560,"sound_type": "licensed","audio_muted": null,"audio_muted_reason": null,"music": {"title": "Azeem-O-Shaan Shahenshah","artist": "A.R. Rahman, Mohammed Aslam, Bonnie Chakravarty","audio_id": "1301690440176351","uses_original_audio": false},"music_trending": false,"ai_label": null,"topics": ["leopard","safari","wildlife","jungle predator"],"latest_comments": [{"id": "1","text": "❤️❤️","timestamp": "2026-10-22T03:00:28Z","likes": 0,"owner_username": "commenter_1","owner_id": null,"owner_is_verified": false,"gif_url": null},{"id": "2","text": "Amazing capture 🔥","timestamp": "2026-10-17T16:49:35Z","likes": 1,"owner_username": "commenter_2","owner_id": null,"owner_is_verified": false,"gif_url": null}],"first_comment": "❤️❤️","details_status": "served","post_count": null,"hashtag_id": null,"hashtag_name": null,"related_keywords": null,"description": null,"verdict": null,"reels_listed": null,"reels_delivered": null,"avg_plays": null,"median_plays": null,"avg_likes": null,"median_likes": null,"avg_comments": null,"median_comments": null,"top_creators": null,"note": null,"scraped_at": "2026-10-22T04:13:23Z"}
Pricing
Pay for the reels a run delivers, plus one run start; no platform usage is billed to you. The reel price falls with your Apify plan.
| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
Reel (reel) | per 1,000 | $2.70 | $2.295 | $1.89 | $1.35 |
Run start (start) | per run | $0.0018 | $0.0018 | $0.0018 | $0.0018 |
A reel is $2.70 per 1,000 on the Free plan ($0.0027 a reel) and $2.295 on Starter, with everything it carries: the details (owner name, music, location, tags, latest comments), and the views and the owners' followers when you ask for them, are inside the reel's price. Each run that delivers a reel also pays the run start, $0.0018 once; a run that delivers none pays nothing at all. So a hashtag's top 20 reels cost $0.0558 on the Free plan and $0.0477 on Starter; two keywords to the end of their lists (about 130 reels) $0.3528 and $0.30015; 1,000 reels $2.7018 and $2.2968; several hashtags and keywords in one run share one start. Free: every hashtag's or keyword's search row (the post count, the related keywords), a term with no ranked list, a term Instagram does not know, a value that names nothing, a reel listed under two of your inputs (one row, one charge), a reel a filter or onlyNewReels leaves out, and an input left unread at maxItems or the time limit. A run that stops early (a timeout, an abort) is charged for the reels it delivered. maxItems counts the charged reels. Before the first request the log names the price of a reel at your plan, the run start and the most the run can cost: maxReelsPerInput (at most 100) a hashtag or keyword and each related keyword walked, under maxItems and your charge limit. Instagram's ranked list ends sooner: about 50 to 70 reels a term (natgeo 59, nature 53, street food bangkok and woodworking 65 each on our runs), so a run to the lists' end costs less than its maximum. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.
Usage patterns
- What to give —
hashtags: with or without#, or a hashtag link (instagram.com/explore/tags/natgeo/,instagram.com/popular/natgeo/).keywords: words or phrases, or a search-results link. Both lists give the same thing: Instagram's ranked reels for the term. A value is lower-cased (Instagram's list is case-sensitive),#and spaces at its ends are dropped, accents and scripts are kept. A term given twice is read once; a value that names nothing (a profile or post link, another site) is a freeinvalid_inputrow. - How many reels —
maxReelsPerInput(20 by default, 100 = to the list's end) takes each list's top reels in Instagram's order; a reel a filter leaves out or already delivered under another input does not count.maxItemscaps the charged rows of the whole run; the inputs are read side by side, so a cap under what they need is shared as their reels arrive, not in input order (each input still gets its top-ranked reels, and its search row says RUN_CAP). A ranked list holds about 50 to 70 reels: that is Instagram's list, not a limit of this Actor, and the search row says how many it held. - Filters —
newerThanandolderThan(a date, a date and time, or7 days) keep the reels published in a window;minPlays,minLikesandminCommentskeep a reel only above a count (a hidden like count does not pass a minimum above 0). The ranked list is not in date order, so a filter reads the whole list; a reel left out is free and frees its place. - Related keywords — Each search row lists Instagram's related keywords (
relatedKeywordsCount, 10 by default, up to 48).relatedKeywordsDepthalso reads the ranked reels of each input's first N related keywords: each is a whole list of its own, its rows sayinput_typerelated andrelated_tothe input. A reel already delivered under another input is not delivered twice. - Scheduled runs: only the new reels — Save a task with
onlyNewReels(and astateStoreNameto name the memory) and schedule it: each run delivers the reels of the ranked list that the memory never delivered, so a daily task follows the reels that enter a hashtag's top list. A reel the memory knows is skipped free. The memory keeps the newest 20,000 reel ids.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
hashtags | array | [] | Hashtags, one per line, with or without # (natgeo, #natgeo), or a hashtag link (https://www.instagram.com/explore/tags/natgeo/, instagram.com/popular/natgeo/). Each gives Instagram's ranked reels for it, top first, up to maxReelsPerInput, and one free search row with the hashtag's post count and related keywords. Upper case is read as lower case (Instagram's list is case-sensitive); accents and other scripts are kept (café and cafe are two terms, ラーメン works). A value that names nothing is a free row that says why. |
keywords | array | [] | Search keywords or phrases, one per line (skincare routine, street food bangkok), or a search-results link (instagram.com/explore/search/keyword/?q=…). Each gives the ranked reels Instagram shows for the search, the same as a hashtag. A keyword and a hashtag with one spelling are read once. |
maxReelsPerInput | integer | 20 | How many of each list's top reels, in Instagram's order. A ranked list holds about 50–70 reels (natgeo 59, nature 53 on our runs); 100 = every reel to the list's end. A reel left out by a filter or already delivered under another input does not count. The search row says how many the list held and why the walk stopped. |
includeDetails | boolean | true | Read each reel's own record: the owner's full name and verified flag, the music title and artist, the location with coordinates, the tagged accounts, the coauthors, the latest comments (up to 15), Instagram's alt text and topic tags, the edited flag. On by default. Off = a faster, lighter run with the lists' fields only (plays, time, likes, comments, caption, owner username, media URLs, duration, the sound's kind). |
includeViews | boolean | false | Add views, the counter Instagram's embed page shows (a quarter to a half of the plays; the plays are on every row anyway). One more call a reel: a run takes longer. |
includeOwnerFollowers | boolean | false | Add each reel owner's follower count (owner_followers) and the engagement rate per follower (engagement_rate). One call per distinct owner. |
newerThan | string | "" | Only reels published on or after this date: 2026-09-01, a date and time (2026-09-01T12:00:00Z), or a span back from now in lower case (7 days, 12 hours, 2 weeks, 3 months). The whole ranked list is read and the reels outside the window are left out, free. |
olderThan | string | "" | Only reels published on or before this date (a date includes its whole day), in the same forms as newerThan. |
minPlays | integer | 0 | Keep a reel only with at least this many plays (a reel of the list's tail, which Instagram serves without plays, is left out when this is above 0). Free when it leaves a reel out. 0 = every reel. |
minLikes | integer | 0 | Keep a reel only with at least this many likes (a reel whose owner hides the likes is left out when this is above 0). Free when it leaves a reel out. 0 = every reel. |
minComments | integer | 0 | Keep a reel only with at least this many comments. Free when it leaves a reel out. 0 = every reel. |
relatedKeywordsCount | integer | 10 | How many of Instagram's related keywords the search row lists (related_keywords); Instagram serves up to 48. |
relatedKeywordsDepth | integer | 0 | Also read the ranked reels of each input's first N related keywords (each a list of its own, with input_type related and related_to naming its input). A reel already delivered under another input is not delivered twice. 0 = the inputs only. |
onlyNewReels | boolean | false | Deliver only the reels an earlier run with the same memory never delivered: a ranked list changes from day to day, so a scheduled task gets the reels that entered the list since. A reel the memory knows is skipped free. |
stateStoreName | string | "" | The name of the memory onlyNewReels keeps (letters, digits, '.', '_', '-'); empty = a name derived from the inputs. |
maxItems | integer | 0 | The most charged rows (reels) of the whole run, over every hashtag, keyword and related keyword; 0 = no cap beyond maxReelsPerInput and your charge limit. The inputs are read side by side, so a cap under what they need is shared as their reels arrive, not in input order: each input still gets its top-ranked reels, and its search row says RUN_CAP. |
proxyUrl | string | Your own proxy (scheme://user:pass@host:port) for every call instead of ours. Leave empty: the Actor brings its own connections at no cost to you. |
Errors
A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:
- the status message starts with
INPUT REJECTED; - the dataset holds one row,
{"error": true, "code": "…", "message": "…"}, and no results; - the key-value store record
ERRORholds the same object.
From code, check error on the first row before reading results.
A hashtag or keyword Instagram shows no ranked list for, a term it does not know as typed, or a value that names nothing is not an error: it gets one free search row with its status and Instagram's own reason, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.
FAQ
Does it get the newest posts of a hashtag?
No: it gets the reels Instagram ranks for the hashtag or keyword, top first — the list Instagram shows logged out on a hashtag's and a search's page. Instagram does not show a hashtag's newest posts, or photos and carousels, to logged-out viewers; the scrapers that sell them read them with a logged-in account. Use newerThan to keep only recent reels of the ranked list.
Why do I get about 50 to 70 reels, not thousands?
That is the length of Instagram's ranked list for a term: the walk reads it to Instagram's own end flag (natgeo 59, nature 53 on our runs) and the search row's verdict says COMPLETE with the length. For more reels on a subject, add more hashtags or keywords, or let relatedKeywordsDepth read the related keywords' lists: each is a different list.
Why are some likes null?
The owner hid the like count on that reel. Instagram then serves a placeholder number, not the count, so the row gives likes null and likes_hidden true. The comment count and the plays are still there.
Why do the last few reels have no plays?
Instagram serves the plays with the first 52 to 68 reels of a list; its last 1 to 11 reels come without a play count. Those rows have plays null and plays_status not_in_ranked_head; everything else is there.
What is the hashtag's post count on a keyword?
The post count of the hashtag spelled as the keyword without spaces (skincare routine → #skincareroutine), as Instagram's own hashtag search shows it. When Instagram lists no such hashtag (a long phrase), post_count is null and the note says so.
What are the free rows?
One search row per hashtag or keyword (record_type search): ok with the figures, the verdict and the counts, or why it gave no reel — no_ranked_list (Instagram knows the term and shows no ranked list for it; its description and post count are on the row), unknown_term (Instagram does not know the term as typed: try another spelling), invalid_input, failed, not_read. Only reels are charged. For reels alone keep the rows whose record_type is reel.
Does it need an Instagram account, cookies or a login?
No. Everything is read from Instagram's public logged-out data with a plain HTTP client; nothing of yours is sent to Instagram.
Does it give shares, saves or reposts?
No. Instagram does not serve the share, save and repost counts to logged-out viewers. Each row has the plays, the likes and the comment count.
How long do the video and image URLs work?
Instagram signs every media URL with an expiry, 1 to 4 days after the read; each row gives that time in media_urls_expire_at. Download what you need before it.
I move from another Instagram hashtag scraper: which column is which?
The usual keys map one to one: shortCode → shortcode, caption, hashtags, mentions → the same, timestamp → timestamp, likesCount → likes (+ likes_hidden), commentsCount → comments_count, videoPlayCount → plays, videoViewCount → views, videoDuration → video_duration, ownerUsername / ownerId / ownerFullName → owner_username / owner_id / owner_full_name, musicInfo → music, coauthorProducers → coauthors, taggedUsers → tagged_users, locationName → location_name, displayUrl → display_url, videoUrl → video_url, latestComments → latest_comments, inputUrl → input, a rank or position → rank.
Integration
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('hyperbach/instagram-hashtag-scraper').call({"hashtags": ["natgeo"], "maxReelsPerInput": 20});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('hyperbach/instagram-hashtag-scraper').call(run_input={'hashtags': ['natgeo'], 'maxReelsPerInput': 20})items = client.dataset(run['defaultDatasetId']).list_items().items
CLI
$apify call hyperbach/instagram-hashtag-scraper --input '{"hashtags": ["natgeo"], "maxReelsPerInput": 20}'
REST
curl -X POST "https://api.apify.com/v2/acts/hyperbach~instagram-hashtag-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' -d '{"hashtags": ["natgeo"], "maxReelsPerInput": 20}'
Support
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.