Instagram API Scraper By Likes, Keywords & Date Range avatar

Instagram API Scraper By Likes, Keywords & Date Range

Pricing

from $3.99 / 1,000 results

Go to Apify Store
Instagram API Scraper By Likes, Keywords & Date Range

Instagram API Scraper By Likes, Keywords & Date Range

Pricing

from $3.99 / 1,000 results

Rating

0.0

(0)

Developer

Scraply

Scraply

Maintained by Community

Actor stats

0

Bookmarked

10

Total users

2

Monthly active users

9 days ago

Last modified

Share

Instagram Scraper โ€” Posts & Reels by Likes, Keywords, Dates

Instagram Scraper By Likes, Keywords & Date Range scans a public Instagram profile's timeline posts, reels or @mentions and keeps only the ones that pass your filters โ€” minimum likes, comments or views, caption keywords to include or exclude, a two-sided posted-after / posted-before window, and a photo/video/reel/carousel filter. Every match ships as typed JSON with likesCount, commentsCount, viewCount, caption, hashtags, matchedKeywords and mediaCategory already attached. Social media managers, competitive analysts and lead-gen teams use it to pull only the posts that matter instead of paging a whole feed by hand.

โš ๏ธ Read this before your first run: scanBudget and keepPerTarget are two different caps. scanBudget limits how many posts get examined; keepPerTarget limits how many matches get kept. A tight scanBudget with a strict minLikes can return zero rows even with keepPerTarget set high โ€” the run gives up scanning before it ever finds enough qualifying posts. If a run comes back empty, widen scanBudget first.

๐Ÿ“ธ What is Instagram Scraper By Likes, Keywords & Date Range?

It is an Apify Actor that pages a public Instagram profile's feed through Instagram's own logged-out web API and applies your filters while it pages โ€” the dataset holds matches, not a spreadsheet you still have to sort. No Instagram account, login, cookie or session is required; every field returned is already visible to an anonymous visitor on the profile.

  • ๐ŸŽฏ Point it at any public profile by URL or bare username (filterTargets) โ€” no login needed
  • ๐Ÿ—‚๏ธ Choose the feed to scan: timeline posts, the reels-only clips feed, or @mentions found inside matching posts (contentMode)
  • ๐Ÿ“Š Set engagement floors on likes, comments and video views, with honest rejection reasons instead of silent zeros
  • ๐Ÿ”ค Filter captions with an include list (any/all) and a separate exclude list
  • ๐Ÿ“† Close a two-ended posted-after / posted-before date window, absolute or relative
  • ๐Ÿ–ผ๏ธ Restrict output to a single media type โ€” photo, video, reel or carousel
  • ๐Ÿ“ฆ Export matches as JSON, CSV or Excel through the Apify dataset, with an uncharged per-profile filter-audit row included by default

What data can I extract with Instagram Scraper By Likes, Keywords & Date Range?

A matching post or reel is one dataset row carrying identity, engagement, caption and filter-provenance fields together โ€” every key below is read straight off the row-building code, not the shorter list the default dataset view shows.

FieldExample ValueUse Case
id"3234567890123456789"Instagram's internal media ID
type"Video"Photo, Video or Sidecar (carousel), from the raw payload
shortCode"Cx1AbCdEfGh"Instagram's shortcode, used to rebuild the post URL
caption"New collection drops Friday #nyc"Full caption text
hashtags["nyc"]Hashtags parsed out of the caption
mentions["humansofny"]@usernames parsed out of the caption
url"https://www.instagram.com/p/Cx1AbCdEfGh/"Direct post link
commentsCount842Comment count at scrape time
firstComment""First comment text, when the feed payload carried inline comments (usually empty โ€” see note below)
latestComments[]Inline comments the feed happened to embed โ€” see nested shape below
dimensionsHeight1350Media height in pixels
dimensionsWidth1080Media width in pixels
displayUrl"https://scontent.cdninstagram.com/โ€ฆ"Best-available image/cover URL
images["https://scontent.cdninstagram.com/โ€ฆ"]Display image plus one URL per carousel child
alt"Two people standing on a rooftop at night"Instagram's own accessibility caption, or null
likesCount54213Like count at scrape time
timestamp"2026-06-14T18:32:00.000Z"Post date, ISO 8601 UTC
childPosts[]Carousel children โ€” see nested shape below
ownerFullName"Humans of New York"Profile display name
ownerUsername"humansofny"Profile username
ownerId"185253363"Profile's numeric Instagram ID
isCommentsDisabledfalseWhether the post owner turned comments off
inputUrl"humansofny"The exact filterTargets entry this row came from
parentData{"name": "humansofny", "type": "profile", "url": "https://www.instagram.com/humansofny/"}Only present when attachSourceMetadata is on
viewCount128430Video/reel plays; null on photos and carousels (no view metric exists there)
mediaCategory"reel"photo, video, reel or carousel, derived from the payload
likeCountsHiddenfalsetrue when the owner hid like counts โ€” likesCount is not faked as 0 in that case
matchedKeywords["nyc"]Which captionKeywords terms actually fired on this caption
filtersPassed["minLikes", "captionKeywords"]Which active rules this row satisfied
filtersApplied2How many filter rules were active for the run
scrapedAt"2026-07-26T09:41:12.000Z"When this row was scraped, ISO 8601 UTC
section"posts"posts, reels, mentions or audit โ€” set by the Actor, not by Instagram

A row carries 31 fields on every run, 32 when attachSourceMetadata adds parentData. The default dataset view shows only 18 of them (type, mediaCategory, shortCode, ownerUsername, caption, matchedKeywords, likesCount, commentsCount, viewCount, likeCountsHidden, timestamp, filtersPassed, filtersApplied, url, displayUrl, hashtags, inputUrl, scrapedAt) โ€” switch to the Console's "Reels view", "Mentions view" or "Filter audit" tab, or just read the JSON/CSV export, to see the rest.

Nested objects, filter provenance, and the honest zero

latestComments is an array of comment objects (id, text, ownerUsername, ownerProfilePicUrl, timestamp, repliesCount, replies, likesCount, and a nested owner object with Instagram's own username, profile_pic_url, is_verified, id, full_name, is_mentionable, is_private, profile_pic_id and latest_reel_media keys). This variant does not fetch per-post comment detail, so latestComments and firstComment are populated only when Instagram's feed listing happened to embed inline comments โ€” in practice they are usually empty. childPosts is an array with the same shape as a top-level post (minus caption/engagement) for each carousel child, populated only when mediaCategory is "carousel".

filtersPassed, matchedKeywords, viewCount, mediaCategory and likeCountsHidden are never guessed: a photo's viewCount is null (not 0) because photos carry no view metric logged-out, and a post whose owner hid like counts is rejected with reason likes_hidden rather than silently compared against 0.

Three feed modes produce three different row shapes

contentMode picks which feed of the profile gets scanned and filtered โ€” pick one per run:

  • posts (default) โ€” the timeline grid: photos, videos and carousels, in the 31/32-field shape documented above, section: "posts".
  • reels โ€” the dedicated clips feed only. Same field shape, but type is forced to "Video" and section is "reels". If Instagram's clips endpoint is unreachable, the Actor falls back to reading reels out of the timeline feed instead of returning an empty run โ€” the audit row's reelsSource field then reads "timeline_feed_fallback".
  • mentions โ€” a derived row type, not the post itself. The Actor first runs the same posts pipeline (same filters, same scanBudget/keepPerTarget) internally, then emits one row per @mention found inside each post that passed. A mentions row has a different, smaller shape: type ("mention"), mentionedUsername, postShortCode, postUrl, ownerUsername, timestamp, inputUrl, section ("mentions") โ€” 8 fields, no engagement or filter-provenance keys, because those live on the post that produced it, not on the mention.

The uncharged filter-audit row

With includeFilterAudit on (default true), one extra row is pushed per filterTargets entry โ€” and it is never billed, regardless of contentMode. It carries: type ("filter_audit"), isAudit (true), inputUrl, target, targetKind, contentMode, postsScanned, postsKept, postsRejected, keepRate, rejectedBy (an object counting every rejection reason โ€” below_min_likes, likes_hidden, no_view_metric, keyword_not_found, excluded_keyword, older_than_window, newer_than_window, media_type_mismatch, and more), filtersActive, pagesFetched, scanBudgetReached, reelsSource, errorReason, modeSubstituted, scrapedAt, section ("audit") โ€” 19 fields, only 15 of which appear in the Console's default "Filter audit" view.

Two separate things trigger this row:

  1. Every normal run gets one audit row per profile, so a 120-scanned / 4-kept run is auditable instead of looking broken.
  2. A single post, reel or hashtag URL passed into filterTargets. Those surfaces are login-walled for a logged-out client โ€” Instagram returns nothing for them without a session. Instead of a silent empty run, the audit row's errorReason names exactly why: post_detail_login_walled, hashtag_surface_login_walled, no_items_returned (private or empty account), or feed_fetch_failed (network/proxy failure after 3 retries). If includeFilterAudit is turned off, a login-walled single-URL target produces no row at all for that target.

To exclude audit rows from your paid results when reading the dataset (via the API, a filter, or downstream code), keep only rows where type is not "filter_audit" โ€” equivalently, where isAudit is not true:

matches = [row for row in items if row.get("type") != "filter_audit"]

Why not build this yourself?

Meta's Instagram Graph API is the platform's own official API, and it is built for a different job: it only returns data for Instagram Business or Creator accounts that have explicitly connected to your app โ€” you cannot point it at an arbitrary public profile you do not own or manage on behalf of a client. It has no endpoint for caption-keyword search, no engagement-threshold parameter, and no two-sided date-range query over someone else's feed. For the exact use case this Actor covers โ€” "show me this account's posts that cleared 50,000 likes and mention a keyword last quarter" over a profile that is not yours โ€” there is no official API path at all, for you or for anyone else.

The alternative is a DIY scraper: reverse-engineer Instagram's logged-out web endpoints, handle pagination and rate limiting, build a caption-keyword and engagement filter engine, and maintain a proxy escalation ladder for when Instagram starts blocking. This Actor does all of that already โ€” filtering happens while the feed is being paged, live, against a public feed endpoint, with the proxy ladder and filter engine already built and maintained.

How to use data extracted from Instagram

๐Ÿ“ฑ Social media managers and marketers

A social media manager auditing a competitor's account sets filterTargets to that profile, minLikes to a threshold above the account's typical post, and a wide scanBudget โ€” then reads likesCount, caption and timestamp off the matches to see exactly which content formats and topics outperform for that brand.

๐Ÿข Agencies benchmarking clients

An agency running the same audit across a client's competitor set repeats the run once per profile with the same filters โ€” minLikes, mediaTypeFilter and a fixed postedAfter/postedBefore window โ€” so every competitor is measured against the same bar for the same period, and the filtersPassed field confirms each row cleared the same rules.

๐Ÿ“Š Market and campaign research

A researcher tracking how a hashtag campaign performed sets captionKeywords to the campaign tag with keywordMatchMode: "any", a postedAfter/postedBefore window matching the campaign dates, and reads likesCount, commentsCount and matchedKeywords across every profile that ran the tag to compare which accounts' posts about it actually landed.

๐Ÿค– AI agents and automated pipelines

An agent tool wraps this Actor to answer "did this account post anything about X that did numbers last month" on demand โ€” the typed JSON row (caption, engagement counts, matchedKeywords, timestamp) drops straight into an LLM context or a vector store with no parsing step, and the uncharged audit row lets the agent report "0 matches, but only 40 posts were scanned" instead of a bare empty list.

๐Ÿ”ผ Input sample

ParameterRequiredTypeDescriptionExample Value
filterTargetsNoarrayInstagram profile URLs or bare usernames whose feed should be scanned and filtered. Single post, reel and hashtag URLs are accepted too, but produce an uncharged audit row instead of results (see above).["humansofny"]
contentModeNostringWhich feed to scan. Default "posts". Enum: "posts" (๐Ÿ“ท Timeline posts), "reels" (๐ŸŽฌ Reels feed), "mentions" (๐Ÿ”– Mentions found in posts)."posts"
keepPerTargetNointegerMatching items to keep per profile. Minimum 1, maximum 2400. Default 10.20
scanBudgetNointegerMax posts to scan per profile before giving up. Minimum 0, maximum 2400. 0 = no cap (engine ceiling ~2,400 posts). Default 120.300
minLikesNointegerMinimum likes. Minimum 0. Default 0 (off).50000
minCommentsNointegerMinimum comments. Minimum 0. Default 0 (off).0
minViewsNointegerMinimum views, video only. Minimum 0. Default 0 (off).0
captionKeywordsNoarrayCase-insensitive substrings the caption must contain. Hashtags work too.["nyc"]
keywordMatchModeNostringHow to combine captionKeywords. Default "any". Enum: "any" (๐Ÿ”€ OR), "all" (๐Ÿ”’ AND)."any"
captionKeywordsExcludeNoarrayCase-insensitive substrings that disqualify a post.["giveaway"]
postedAfterNostringLower edge of the date window. Absolute ("2026-01-31") or relative ("7 days", "2 months", "1 year")."2026-01-01"
postedBeforeNostringUpper edge of the date window. Absolute or relative."2026-06-30"
mediaTypeFilterNostringWhich media types to keep. Default "any". Enum: "any", "photo", "video", "reel", "carousel"."any"
includeFilterAuditNobooleanAdd an uncharged filter-audit row per profile. Default true.true
attachSourceMetadataNobooleanAttach a parentData object (source profile name/type/URL) to every result row. Default false.false
proxyConfigurationNoobjectProxy configuration. Default {"useApifyProxy": false} โ€” direct connection, escalating automatically if blocked.{"useApifyProxy": false}

Example input

{
"filterTargets": ["humansofny"],
"contentMode": "posts",
"keepPerTarget": 20,
"scanBudget": 300,
"minLikes": 50000,
"captionKeywords": ["nyc"],
"keywordMatchMode": "any",
"captionKeywordsExclude": ["giveaway"],
"postedAfter": "2026-01-01",
"postedBefore": "2026-06-30",
"mediaTypeFilter": "any",
"includeFilterAudit": true,
"attachSourceMetadata": false
}

Common pitfall: raising keepPerTarget does nothing if scanBudget is too small to reach that many qualifying posts. scanBudget is the number of posts examined; keepPerTarget is the number of matches kept. Fix an empty-looking run by raising scanBudget, not keepPerTarget.

๐Ÿ”ฝ Output sample

Typed, normalized JSON, one row per matching post, reel or mention, plus one uncharged audit row per profile. Export as JSON, CSV or Excel through the Apify dataset, or read it through the Apify API.

Example output โ€” a matching post (contentMode: "posts")

{
"id": "3234567890123456789",
"type": "Sidecar",
"shortCode": "Cx1AbCdEfGh",
"caption": "New collection drops Friday #nyc",
"hashtags": ["nyc"],
"mentions": [],
"url": "https://www.instagram.com/p/Cx1AbCdEfGh/",
"commentsCount": 842,
"firstComment": "",
"latestComments": [],
"dimensionsHeight": 1350,
"dimensionsWidth": 1080,
"displayUrl": "https://scontent.cdninstagram.com/v/example.jpg",
"images": ["https://scontent.cdninstagram.com/v/example.jpg"],
"alt": "Two people standing on a rooftop at night",
"likesCount": 54213,
"timestamp": "2026-06-14T18:32:00.000Z",
"childPosts": [],
"ownerFullName": "Humans of New York",
"ownerUsername": "humansofny",
"ownerId": "185253363",
"isCommentsDisabled": false,
"inputUrl": "humansofny",
"viewCount": null,
"mediaCategory": "carousel",
"likeCountsHidden": false,
"matchedKeywords": ["nyc"],
"filtersPassed": ["minLikes", "captionKeywords"],
"filtersApplied": 2,
"scrapedAt": "2026-07-26T09:41:12.000Z",
"section": "posts"
}

Example output โ€” the uncharged filter-audit row

{
"type": "filter_audit",
"isAudit": true,
"inputUrl": "humansofny",
"target": "humansofny",
"targetKind": "profile",
"contentMode": "posts",
"postsScanned": 120,
"postsKept": 4,
"postsRejected": 116,
"keepRate": 0.0333,
"rejectedBy": {"below_min_likes": 109, "excluded_keyword": 7},
"filtersActive": ["minLikes", "captionKeywords", "captionKeywordsExclude"],
"pagesFetched": 10,
"scanBudgetReached": true,
"reelsSource": null,
"errorReason": null,
"modeSubstituted": null,
"scrapedAt": "2026-07-26T09:41:20.000Z",
"section": "audit"
}

Example output โ€” a mention row (contentMode: "mentions")

{
"type": "mention",
"mentionedUsername": "brooklynvintage",
"postShortCode": "Cx1AbCdEfGh",
"postUrl": "https://www.instagram.com/p/Cx1AbCdEfGh/",
"ownerUsername": "humansofny",
"timestamp": "2026-06-14T18:32:00.000Z",
"inputUrl": "humansofny",
"section": "mentions"
}

How do you filter and target specific posts?

filterTargets accepts profile URLs or bare usernames โ€” that is the only target type this Actor scans and filters (single post/reel/hashtag URLs are still accepted but return an audit row only, per above). Real precision comes from four levers working together, in a fixed order:

  1. Scope, first. scanBudget decides how many posts get examined per profile before the run gives up; keepPerTarget decides how many of the examined posts that pass filters get kept. Filtering happens strictly inside the scanned set โ€” a strict minLikes with a small scanBudget can legitimately return nothing.
  2. Engagement floors. minLikes, minComments and minViews each reject honestly rather than guessing: a post whose owner hid like counts is rejected as likes_hidden, not compared against a fake 0; a photo checked against minViews is rejected as no_view_metric, since photos carry no view count at all.
  3. Caption wording. captionKeywords with keywordMatchMode: "any" keeps a post if at least one term appears (OR); "all" keeps it only if every term appears (AND). captionKeywordsExclude is then applied on top โ€” any post containing an excluded term is dropped even if it matched the include rule. Every include term that fired is reported back in matchedKeywords; case is ignored throughout.
  4. Date window and media type. postedAfter / postedBefore accept absolute ("2026-01-31") or relative ("7 days", "2 months", "1 year") values and both ends can be set together to isolate a single month or quarter. mediaTypeFilter matches on the payload's own product_type/media_type: "photo" and "carousel" match only their own category, "reel" matches only clips-product posts, and "video" matches both video and reel categories (a reel is a video).

Three real examples:

Viral-post finder โ€” a handful of the account's biggest hits, scanning deep:

{ "filterTargets": ["humansofny"], "minLikes": 100000, "keepPerTarget": 5, "scanBudget": 2000 }

Campaign audit โ€” every on-brand post from a quarter, excluding giveaways:

{ "filterTargets": ["humansofny"], "captionKeywords": ["nyc", "collection"], "keywordMatchMode": "all", "captionKeywordsExclude": ["giveaway", "#ad"], "postedAfter": "2026-01-01", "postedBefore": "2026-03-31" }

Reels engagement scan โ€” only reels that cleared a view floor:

{ "filterTargets": ["humansofny"], "contentMode": "reels", "minViews": 200000, "mediaTypeFilter": "reel" }

โ–ถ๏ธ Want to try other Instagram scrapers?

Scraper NameWhat it extracts
Instagram Followers Count ScraperFollower, following and post counts plus full public profile data from a username or URL
Instagram Comment Engagement ScraperA post or reel's comment section โ€” comments, replies and per-comment engagement metrics
Instagram Reels Hashtag ScraperReels by hashtag with audio metadata, a minimum play-count filter and engagement ranking
Instagram Profile Engagement EstimatorA profile's engagement rate estimated from its follower base and a sample of recent posts
Instagram Brand Mention TrackerInbound posts where other accounts tag or @mention a brand handle, with keyword filtering
Instagram Single Reels ScraperA single Reel URL โ€” caption, like/comment/play counts, video and thumbnail URLs, music metadata and comments

How to extract Instagram data programmatically

Instagram Scraper By Likes, Keywords & Date Range runs on Apify: one API call starts the run, structured JSON comes back from the dataset. No separate developer account or API key for Instagram itself โ€” only your Apify token.

Python example

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/instagram-api-scraper-by-likes-keywords-date-range").call(run_input={
"filterTargets": ["humansofny"],
"contentMode": "posts",
"minLikes": 50000,
"captionKeywords": ["nyc"],
"keepPerTarget": 20,
"scanBudget": 300,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row.get("type") == "filter_audit":
continue
print(row["shortCode"], row["likesCount"], row["matchedKeywords"])

Works in Go, Ruby, Node.js, cURL โ€” any language that can call the Apify API.

Export to spreadsheets or CRM

Export the dataset as CSV directly from the Apify Console or API. Flat keys โ€” likesCount, commentsCount, caption, url, ownerUsername, timestamp โ€” map straight to spreadsheet columns; nested keys like latestComments and childPosts serialize as JSON strings in the CSV, ready to re-parse downstream or in an Airtable/Sheets automation step.

Scraping publicly accessible Instagram content is broadly permissible when no login or access control is bypassed, and this Actor collects only what an anonymous visitor already sees on a profile's public feed. Every row is still built around the identity of the profile it came from โ€” ownerUsername, caption, engagement counts and timestamps are tied to a specific, identifiable account โ€” so this output is personal data under GDPR and CCPA, not anonymous business records. A lawful basis (typically legitimate interest) is needed to store and process it, the profile owner's rights (access, deletion) still apply, and it does not cover private accounts or anything Instagram gates behind a login. Consult legal counsel for commercial applications involving bulk storage of personal data.

โ“ Frequently asked questions

What if a profile has zero posts matching the filters within the scan budget?

The run still returns a row: the uncharged filter-audit row, with postsScanned and postsKept: 0, rejectedBy broken down by reason, and scanBudgetReached: true if the budget ran out before enough matches were found. Zero matches with scanBudgetReached: true means "raise scanBudget and try again"; zero matches with scanBudgetReached: false means the account genuinely has nothing that clears your filters.

Can I get reels and posts in the same run?

Not in one run โ€” contentMode scans one feed at a time (posts, reels or mentions). Run the Actor twice against the same filterTargets with different contentMode values to cover both.

How accurate is the likes/views/comments data?

The Actor returns counts exactly as Instagram's feed API reports them at request time. Some owners hide like counts โ€” those rows carry likeCountsHidden: true and are rejected rather than compared against a fake 0 if minLikes is set. View counts exist only for videos and reels; photos and carousels report viewCount: null, never 0.

How many posts can I get per run?

keepPerTarget caps matches kept, from 1 to 2400 (default 10). scanBudget caps posts examined before giving up, from 0 (no cap) to 2400 (default 120) โ€” 0 still bottoms out at the engine's own ~2,400-post pagination ceiling. Both caps apply per filterTargets entry, not across the whole run.

What's the difference between scanBudget and keepPerTarget?

scanBudget is a scanning limit โ€” how many posts get examined, newest first. keepPerTarget is a keeping limit โ€” how many of those examined posts, after filters, get saved. A run stops as soon as either limit is hit, whichever comes first. Raising keepPerTarget alone cannot produce more matches if scanBudget runs out before enough qualifying posts are found.

Does Instagram Scraper By Likes, Keywords & Date Range work with Claude, ChatGPT and AI agent frameworks?

Yes. It is callable as a standard HTTP endpoint through the Apify API, so LangChain, CrewAI, n8n or a hand-written tool definition can invoke it and get typed JSON back with no parsing step.

How does this compare to other Instagram scrapers?

Checked on the Apify Store on 26 July 2026: datadoping/instagram-likes-scraper and scraping_solutions/instagram-engagers-likes-and-comments-no-cookies both extract likers or commenters of a single post, not a profile's own feed filtered by engagement, keywords and date โ€” a structurally different job. patient_discovery/instagram-likes is the same single-post-likers model, documented at $2.50 per 1,000 results on its listing. None of the three documents scanning a profile's timeline or reels feed, filtering on caption keywords, or a two-ended date window โ€” this Actor's targeting axis is the profile itself, filtered down, rather than a single post's engager list.

Can I use this without an Instagram API key or developer account?

Yes. No Instagram account, API key, cookie or session is required โ€” the Actor talks to Instagram's public logged-out feed API directly. The only credential you need is your Apify account to run the Actor.

Conclusion

Instagram Scraper By Likes, Keywords & Date Range turns a profile's entire feed into just the posts, reels or mentions that clear your engagement, keyword and date rules โ€” with an uncharged audit row so a low match count is explained, not mysterious. It is built for anyone who needs a filtered slice of a public account's content rather than a full re-export of the feed. Open it on the Apify Console or call it through the Apify API to start a run.