Instagram Post Scraper (Sponsored Post Finder)
Pricing
from $5.99 / 1,000 results
Instagram Post Scraper (Sponsored Post Finder)
Instagram Post Scraper extracts post details and identifies sponsored content, including captions, hashtags, engagement metrics, creator details, timestamps, media URLs, and sponsorship signals. Ideal for influencer research, brand monitoring, competitor analysis, and ad intelligence.
Pricing
from $5.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Instagram Post Scraper — Sponsored Posts, Brand Tags & Ad Cues
Instagram Post Scraper (Sponsored Post Finder) scrapes a public creator's posts, reels and carousels and attaches a sponsorship verdict to every row: Instagram's own official paid-partnership flag, kept strictly separate from a deterministic caption ad-cue check, resolved to a named brand with a confidence label, and rolled up into a same-scan repeat-deal count. Every response is structured JSON, ready to pass directly to an LLM, index into a vector store, or feed a brand-safety monitoring pipeline. Point it at any public handle, profile URL, or single post link and see exactly who is paying whom, and how they disclosed it.
What is Instagram Post Scraper (Sponsored Post Finder)?
It is an Instagram post auditor built on top of a full post scraper: give it one or more public creator handles, profile URLs, or single post/reel/tv URLs, and it returns every post it finds — caption, hashtags, mentions, likes, comments, media, carousel children — plus a sponsorship layer most Instagram scrapers throw away. The brand's identity (handle, display name, verified badge, private/unpublished state, profile picture, numeric ID and follower count) already rides inside the same feed payload every post scraper downloads; this Actor reads it instead of discarding it, at no extra request cost.
Its defining behavior is that it never merges two different kinds of evidence into one boolean. isPaidPartnership is Instagram's own official label — a fact the platform publishes. hasCaptionAdSignal is a deterministic keyword/phrase match against the caption (#ad, #sponsored, "paid partnership", "use code", and more) — an inference from wording. A sponsorshipEvidence field records which of the four states applies (officialAndCaption, officialOnly, captionOnly, none), so a brand that gets tagged but never writes #ad — or a creator who writes #ad on a post Instagram never flagged — shows up as exactly that, instead of being averaged into one number.
⚠️ Sponsored-post rate is creator-driven, not constant. Across the accounts used to build this Actor, it ranged from 0% on 5 of 11 accounts to 38.3% on one (per this Actor's own published input schema). A small scan budget combined with a sponsorship filter can legitimately return zero rows on a creator who simply hasn't posted an ad recently — raise
maxPostsToScanbefore assuming the filter is broken.
No Instagram account, login, or session cookie is required — every request runs against Instagram's public, logged-out feed and post-page surface, using a CSRF token and app ID harvested from the target's own profile HTML.
- 🏷️ Official-vs-caption sponsorship evidence —
isPaidPartnershipandhasCaptionAdSignalreported as two independent fields plus a combinedsponsorshipEvidencelabel - 🎯 Resolved brand identity — handle, display name, verified flag, private/unpublished state, profile picture, numeric ID, profile URL and exact follower count for every Instagram-confirmed sponsor
- 🧭 Deterministic brand inference — when Instagram tags a paid post but won't name the brand, a tagged-user/caption-mention/coauthor ranker proposes a candidate, clearly separated from confirmed sponsorship
- 🔁 In-run repeat-deal rollup — how many times a resolved brand appears in the same scan, and the first/last timestamp of that brand's posts, computed with zero extra requests
- ⚖️ Sponsored-vs-organic engagement index — median likes on sponsored posts ÷ median likes on organic posts, computed from the scan window itself
- 🔎 Filters that don't cost a full re-scan — sponsorship-signal filter, brand allow-list, and minimum sponsor follower count, all applied before any row is charged
What data can you get with Instagram Post Scraper (Sponsored Post Finder)?
A single run returns one flat JSON row per post, mixing the standard post record with the sponsorship-intelligence layer described above.
| Result Type | Extracted Fields | Primary Use Case |
|---|---|---|
| Sponsorship evidence & brand identity | isPaidPartnership, hasCaptionAdSignal, captionAdSignals, sponsorshipEvidence, sponsorshipDataAvailable, sponsorUsername, sponsorFullName, sponsorId, sponsorIsVerified, sponsorIsPrivate, sponsorIsUnpublished, sponsorProfilePicUrl, sponsorFollowerCount, sponsorProfileUrl, sponsorCount, sponsorTagPermission, sponsorTagIsPending, inferredSponsorUsername, inferredSponsorSource, inferredSponsorCandidates, resolvedBrandUsername, resolvedBrandConfidence | FTC disclosure audits, brand-deal tracking, ad-intelligence monitoring |
| Repeat-deal rollup & engagement | sponsorDealCountInRun, isRepeatSponsor, sponsorFirstPostTimestamp, sponsorLastPostTimestamp, sponsoredEngagementIndex | Spotting a brand's ongoing relationship with a creator inside one scan |
| Full post record | inputUrl, id, type, shortCode, caption, hashtags, mentions, url, commentsCount, firstComment, latestComments, dimensionsHeight, dimensionsWidth, displayUrl, images, likesCount, timestamp, childPosts, ownerFullName, ownerUsername, ownerId, isCommentsDisabled, alt, productType, taggedUsers, coauthorProducers, isPinned, scanIndexInProfile | Content research, engagement analysis, UGC discovery |
| Video-specific fields | videoUrl, videoViewCount, videoPlayCount, videoDuration, musicInfo | Reel/video performance analysis |
🎯 Official flag vs. caption cue, resolved to one brand
This is the layer competing Instagram post scrapers don't expose. Instead of a single isSponsored boolean, every row carries Instagram's own paid-partnership tag and a caption-derived ad signal side by side:
{"isPaidPartnership": true,"sponsorUsername": "ridge","sponsorFollowerCount": 1450000,"hasCaptionAdSignal": true,"captionAdSignals": ["#ad"],"sponsorshipEvidence": "officialAndCaption","resolvedBrandUsername": "ridge","resolvedBrandConfidence": "confirmed","sponsorDealCountInRun": 2,"isRepeatSponsor": true}
resolvedBrandUsername prefers the Instagram-confirmed sponsorUsername, falling back to inferredSponsorUsername only when Instagram tagged the post as paid but didn't name a brand — resolvedBrandConfidence tells you which one you got ("confirmed" or "inferred"). A caption-only ad cue with no official tag (sponsorshipEvidence: "captionOnly") is flagged via hasCaptionAdSignal but never resolves to a brand — inference only runs on officially-tagged posts, because a caption @mention alone is not proof of a paid relationship. That distinction is deliberate: it keeps "Instagram confirmed this is paid" and "this caption reads like an ad" from ever being silently merged.
📸 Full post record
Every field a plain post scraper returns ships unchanged: caption with hashtags/mentions already parsed out, engagement (likesCount, commentsCount), media (displayUrl, images, carousel childPosts, video fields for Reels/videos), and owner identity (ownerUsername, ownerFullName, ownerId). With dataDetailLevel set to detailedData (the default), each returned row also carries latestComments, firstComment, alt text and musicInfo — fetched with one extra request per returned row, not per post scanned.
Why not build this yourself?
Instagram has no public, official API for auditing another creator's sponsorship activity. Meta's Instagram Graph API and Basic Display API only expose data for accounts you own and connect through a Business/Creator OAuth flow — neither can tell you whether @some-other-creator's last post was a paid partnership, or who paid for it. There is no "list every post where account X was tagged as a sponsor" endpoint at all.
Building this yourself means solving several non-obvious problems this Actor already handles:
- Instagram's private feed endpoint (
/api/v1/feed/user/{username}/username/?count=12) requires anx-csrftokenandx-ig-app-idheader pulled from the target's own profile HTML — there is no token-issuing endpoint to call instead. - The feed is not perfectly chronological: 7 out-of-order posts were measured in 200 items, so a naive "stop at the first post older than my cutoff" truncates real results. This Actor uses a tolerance window instead of a hard stop.
- Sponsor identity is not where it looks like it should be.
sponsor_tags[0].sponsor_idand.usernamearenullon every live tag observed — the brand's actual handle, name, verification and follower count only exist inside the nestedsponsor_tags[0].sponsorobject. - Instagram names the sponsoring brand on only about half of officially-tagged paid posts. Surfacing a candidate for the rest requires a deterministic, multi-source ranker (tagged user, then caption
@mention, then coauthor) built and tuned from scratch. - A single post/reel/tv URL's page never carries the official paid-partnership flag at all — a scraper that doesn't know this will silently report
falseinstead of "unknown."
What is the difference between a caption ad cue and an official paid-partnership tag?
A caption ad cue is text a creator chose to write — a hashtag like #ad or a phrase like "in partnership with." An official paid-partnership tag is a flag Instagram's own systems attach to the post because the creator used Instagram's branded-content tool to disclose the deal. They are not the same signal, and they disagree more often than most people assume: per this Actor's own published measurements, across 636 posts checked, 28 officially-tagged posts carried no caption cue at all, 18 caption-flagged posts had no official tag, and only 14 posts carried both.
The distinction matters for anyone doing disclosure or compliance work, because a single merged boolean hides exactly the cases worth finding: a brand relationship Instagram confirms but the creator never disclosed in writing, or a creator using ad language on a post Instagram never tagged as paid. Instagram Post Scraper (Sponsored Post Finder) returns both as separate JSON fields — isPaidPartnership for the official tag, hasCaptionAdSignal/captionAdSignals for the caption cue — plus the combined sponsorshipEvidence label (officialAndCaption, officialOnly, captionOnly, none) so you can query for either signal, both, or their disagreement, without recomputing it from raw text yourself.
How to scrape Instagram with Instagram Post Scraper (Sponsored Post Finder)?
- Open Instagram Post Scraper (Sponsored Post Finder) on its Apify Store listing and click Try for free (or Start, if it's already in your account).
- Add one or more creators to 🎯 Creators to audit (
username) — a plain handle, a profile URL, or a single post/reel/tv URL. - Choose your sponsorship filter and budgets: 🏷️ Which posts should come back (
sponsorshipFilter), 📦 Rows returned per creator (resultsLimit), and 🔭 Posts to scan through per creator (maxPostsToScan). - Click Start and let the run finish — the log reports how many posts were officially flagged, caption-flagged, and brand-named in each creator's scan.
- Download results as JSON, CSV, Excel or XML from the Storage tab, or pull them programmatically through the Apify API or
apify_client.
{"username": ["mkbhd", "https://www.instagram.com/natgeo/"],"sponsorshipFilter": "anySponsorshipSignal","resultsLimit": 20,"maxPostsToScan": 500}
How to run multiple creators in one job
username accepts an array, so one run can audit any mix of handles, profile URLs, and single post/reel/tv URLs — each is deduplicated (case-insensitive for profiles, by shortcode for posts) and processed one after another, with its own scan depth, row limit, and filters applied independently. A creator that fails (private profile, empty feed, or an unreachable page) does not stop the run — it's logged as a failure and the remaining creators are still scanned. There is no documented per-creator concurrency setting; targets run sequentially within a single job.
⬇️ Input
Twelve input fields; only username is required.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
username | Yes | array | One entry per creator: a handle (mkbhd), a profile URL (https://www.instagram.com/mkbhd/), or a single post/reel/tv URL (https://www.instagram.com/p/SHORTCODE/). Post URLs return exactly one row each and are exempt from the scan budget — Instagram's post page carries no official paid-partnership flag, so those rows always come back with sponsorshipDataAvailable: false. | ["mkbhd", "https://www.instagram.com/natgeo/"] |
sponsorshipFilter | No | string (enum) | Which posts come back. Default "allPosts" (no filter — identical to a plain post scraper). Options: "allPosts", "officiallySponsored" (Instagram's own tag only), "captionSignalled" (caption cue only), "anySponsorshipSignal" (either signal). | "anySponsorshipSignal" |
sponsorUsernames | No | array | Optional brand allow-list, matched against the resolved brand handle (confirmed sponsor first, inferred candidate second). Default [] (every brand kept). | ["ridge", "bestbuy"] |
minSponsorFollowerCount | No | integer (min 0) | Drops posts whose confirmed sponsor has fewer followers than this. Only Instagram-named sponsors carry a follower count, so any value above 0 also excludes inferred-only rows. Default 0 (off). | 1000000 |
includeInferredSponsors | No | boolean | When Instagram tags a post as paid but doesn't name the brand, a deterministic ranker (tagged user > caption @mention > coauthor) proposes a candidate into inferredSponsorUsername/inferredSponsorSource/inferredSponsorCandidates. Never writes to sponsorUsername or isPaidPartnership. Default true. | false |
resultsLimit | No | integer (min 1, max 100000) | Rows returned and billed per creator. Example: 25 returns at most 25 rows even if 300 posts were scanned to find them. Default 10. | 25 |
maxPostsToScan | No | integer (min 1, max 5000) | How deep to scan per creator while filtering. Only consulted when sponsorshipFilter, sponsorUsernames, or minSponsorFollowerCount is active — with the default "All posts" filter, the scan stops as soon as resultsLimit rows are collected. Default 300 (≈ 25 feed requests, at 12 posts per page). | 1000 |
onlyPostsNewerThan | No | string (date picker, nullable) | UTC cutoff. Absolute (YYYY-MM-DD or a full ISO timestamp) or relative ("3 days", "2 weeks", "6 months", "1 year"). An unparseable value fails the run instead of silently disabling the filter. Default null (no cutoff). | "6 months" |
skipPinnedPosts | No | boolean | Skip posts pinned to the creator's own grid. Pin status is still emitted as isPinned either way. Default false. | true |
dataDetailLevel | No | string (enum) | "detailedData" (default) adds alt text, latest comments, music info and video play count via one extra request per returned row. "basicData" skips that request. Every sponsorship column is available on both levels at no extra cost. | "basicData" |
computeSponsoredEngagementIndex | No | boolean | Adds sponsoredEngagementIndex = median likes on sponsored posts ÷ median likes on organic posts, computed only from this run's scan window. Stays null unless the scan contains at least 5 organic and 1 sponsored post. Default true. | false |
proxyConfiguration | No | object | Apify Proxy configuration. Residential is the default and most reliable at volume; datacenter is a valid, cheaper choice since Instagram's post feed answers on both in testing. Optional — the Actor also runs without a proxy. Default {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
Example JSON input
{"username": ["mkbhd","https://www.instagram.com/natgeo/","https://www.instagram.com/p/C9xY2AbCdEf/"],"sponsorshipFilter": "anySponsorshipSignal","sponsorUsernames": [],"minSponsorFollowerCount": 0,"includeInferredSponsors": true,"resultsLimit": 20,"maxPostsToScan": 500,"onlyPostsNewerThan": "6 months","skipPinnedPosts": false,"dataDetailLevel": "detailedData","computeSponsoredEngagementIndex": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Common pitfall: raising maxPostsToScan alone does nothing if sponsorshipFilter is left at its default "allPosts" and no sponsorUsernames/minSponsorFollowerCount is set — with no active filter, the Actor stops scanning as soon as resultsLimit rows are collected, regardless of how high maxPostsToScan is. The scan budget only kicks in once a sponsorship filter, brand allow-list, or follower threshold is actually turned on.
⬆️ Output
Every post is a single flat JSON object pushed to the dataset, charged under the row_result event. Export as JSON, CSV, Excel or XML from the Apify Console's Storage tab, or read it programmatically via the Apify API or apify_client. The underlying row can carry up to 60 possible keys depending on media type and detail level; three published dataset views curate the most relevant subsets — 🏷️ Sponsorship overview (default, 23 columns), 📸 Full post data (31 columns), and 🤝 Brand deal ledger (15 columns, sponsorship rows only) — but every field documented above exists on the row regardless of which view you're looking at.
Scraped results
[{"inputUrl": "https://www.instagram.com/mkbhd/","id": "3701234567890123","type": "Image","shortCode": "Cabc123XYZ","caption": "This desk setup is unreal, thanks to @ridge for the wallet #ad","hashtags": ["ad"],"mentions": ["ridge"],"url": "https://www.instagram.com/p/Cabc123XYZ/","commentsCount": 812,"dimensionsHeight": 1350,"dimensionsWidth": 1080,"displayUrl": "https://scontent.cdninstagram.com/v/t51.../cover1.jpg","images": ["https://scontent.cdninstagram.com/v/t51.../cover1.jpg"],"likesCount": 128340,"timestamp": "2026-06-02T14:05:11.000Z","childPosts": [],"ownerFullName": "Marques Brownlee","ownerUsername": "mkbhd","ownerId": "163571619","isCommentsDisabled": false,"firstComment": "This thing looks incredible, need one!","latestComments": [{"id": "18070377008012681","text": "This thing looks incredible, need one!","ownerUsername": "some_fan","ownerProfilePicUrl": "https://scontent.cdninstagram.com/v/t51.../fan.jpg","timestamp": "2026-06-02T15:10:02.000Z","repliesCount": 0,"replies": [],"likesCount": 4,"owner": { "id": "52290062017", "is_verified": false, "profile_pic_url": "https://scontent.cdninstagram.com/v/t51.../fan.jpg", "username": "some_fan" }}],"alt": "Photo of a desk setup with a wallet on it","isPaidPartnership": true,"sponsorUsername": "ridge","sponsorFullName": "Ridge Wallet","sponsorId": "179664998","sponsorIsVerified": true,"sponsorIsPrivate": false,"sponsorIsUnpublished": false,"sponsorProfilePicUrl": "https://scontent.cdninstagram.com/v/t51.../ridge.jpg","sponsorFollowerCount": 1450000,"sponsorProfileUrl": "https://www.instagram.com/ridge/","sponsorCount": 1,"sponsorTagPermission": true,"sponsorTagIsPending": false,"captionAdSignals": ["#ad"],"hasCaptionAdSignal": true,"sponsorshipEvidence": "officialAndCaption","sponsorshipDataAvailable": true,"inferredSponsorUsername": null,"inferredSponsorSource": null,"inferredSponsorCandidates": [],"resolvedBrandUsername": "ridge","resolvedBrandConfidence": "confirmed","sponsorDealCountInRun": 2,"isRepeatSponsor": true,"sponsorFirstPostTimestamp": "2026-04-11T10:00:00.000Z","sponsorLastPostTimestamp": "2026-06-02T14:05:11.000Z","sponsoredEngagementIndex": 1.42,"isPinned": false,"scanIndexInProfile": 4},{"inputUrl": "https://www.instagram.com/mkbhd/","id": "3701234567890456","type": "Video","shortCode": "Cdef456UVW","caption": "In partnership with @insta360 for this shoot","hashtags": [],"mentions": ["insta360"],"url": "https://www.instagram.com/p/Cdef456UVW/","commentsCount": 341,"dimensionsHeight": 1920,"dimensionsWidth": 1080,"displayUrl": "https://scontent.cdninstagram.com/v/t51.../cover2.jpg","images": ["https://scontent.cdninstagram.com/v/t51.../cover2.jpg"],"likesCount": 54210,"timestamp": "2026-05-19T09:47:02.000Z","childPosts": [],"ownerFullName": "Marques Brownlee","ownerUsername": "mkbhd","ownerId": "163571619","isCommentsDisabled": false,"firstComment": "Camera quality on this is unreal","latestComments": [],"alt": null,"videoUrl": "https://scontent.cdninstagram.com/v/t50.../reel2.mp4","videoViewCount": 302100,"videoPlayCount": 302100,"videoDuration": 27.4,"productType": "clips","isPaidPartnership": false,"sponsorUsername": null,"sponsorFullName": null,"sponsorId": null,"sponsorIsVerified": null,"sponsorIsPrivate": null,"sponsorIsUnpublished": null,"sponsorProfilePicUrl": null,"sponsorFollowerCount": null,"sponsorProfileUrl": null,"sponsorCount": 0,"sponsorTagPermission": null,"sponsorTagIsPending": null,"captionAdSignals": ["in partnership with"],"hasCaptionAdSignal": true,"sponsorshipEvidence": "captionOnly","sponsorshipDataAvailable": true,"inferredSponsorUsername": null,"inferredSponsorSource": null,"inferredSponsorCandidates": [],"resolvedBrandUsername": null,"resolvedBrandConfidence": null,"sponsorDealCountInRun": null,"isRepeatSponsor": null,"sponsorFirstPostTimestamp": null,"sponsorLastPostTimestamp": null,"sponsoredEngagementIndex": 1.42,"isPinned": false,"scanIndexInProfile": 9},{"inputUrl": "https://www.instagram.com/p/C9xY2AbCdEf/","id": "3660778310592222546","type": "Image","shortCode": "C9xY2AbCdEf","caption": "Somewhere quiet, no caption cues here","hashtags": [],"mentions": [],"url": "https://www.instagram.com/p/C9xY2AbCdEf/","commentsCount": 230,"dimensionsHeight": 1350,"dimensionsWidth": 1080,"displayUrl": "https://scontent.cdninstagram.com/v/t51.../cover3.jpg","images": ["https://scontent.cdninstagram.com/v/t51.../cover3.jpg"],"likesCount": 73473,"timestamp": "2026-06-22T19:00:10.000Z","childPosts": [],"ownerFullName": "National Geographic","ownerUsername": "natgeo","ownerId": "787132","isCommentsDisabled": false,"firstComment": "Amen.","latestComments": [{"id": "18070377008012682","text": "Amen.","ownerUsername": "acostadorego","ownerProfilePicUrl": "https://scontent.cdninstagram.com/v/t51.../fan2.jpg","timestamp": "2026-06-22T20:15:00.000Z","repliesCount": 0,"replies": [],"likesCount": 0,"owner": { "id": "52290062018", "is_verified": false, "profile_pic_url": "https://scontent.cdninstagram.com/v/t51.../fan2.jpg", "username": "acostadorego" }}],"alt": "Photo by National Geographic","isPaidPartnership": null,"sponsorUsername": null,"sponsorFullName": null,"sponsorId": null,"sponsorIsVerified": null,"sponsorIsPrivate": null,"sponsorIsUnpublished": null,"sponsorProfilePicUrl": null,"sponsorFollowerCount": null,"sponsorProfileUrl": null,"sponsorCount": null,"sponsorTagPermission": null,"sponsorTagIsPending": null,"captionAdSignals": [],"hasCaptionAdSignal": false,"sponsorshipEvidence": null,"sponsorshipDataAvailable": false,"inferredSponsorUsername": null,"inferredSponsorSource": null,"inferredSponsorCandidates": [],"resolvedBrandUsername": null,"resolvedBrandConfidence": null,"sponsorDealCountInRun": null,"isRepeatSponsor": null,"sponsorFirstPostTimestamp": null,"sponsorLastPostTimestamp": null,"sponsoredEngagementIndex": null,"isPinned": null,"scanIndexInProfile": null}]
Note the third row: single post/reel/tv URLs always carry isPaidPartnership: null and sponsorshipEvidence: null, not false — Instagram's post page simply doesn't expose the official flag, and this Actor reports that as "unknown" rather than fabricating a negative. sponsorshipDataAvailable: false is the field to check before treating a null as a real answer.
How can I use the data extracted with Instagram Post Scraper (Sponsored Post Finder)?
- 🛡️ Brand safety and compliance teams: filter
sponsorUsernamesdown to your own brand's handle to see every post where you were tagged as a sponsor across any creator, then cross-check rows wherehasCaptionAdSignalisfalsebutisPaidPartnershipistruefor under-disclosed deals worth a compliance note. - 🎤 Influencer marketing and talent managers: before signing a creator, scan their recent posts with no filter to see their true sponsorship rate,
resolvedBrandUsernamehistory, andsponsorDealCountInRunfor existing brand relationships. - 🤖 AI engineers and LLM developers: a grounded agent architecture — an agent issues a run against a creator list, receives structured
sponsorshipEvidenceand brand fields back, and passes them straight into a compliance-checking or brand-monitoring prompt. - 📊 Market and competitive researchers: track which brands are buying placements across a roster of creators, and benchmark
sponsoredEngagementIndexto see whether sponsored content underperforms organic posts for a given account.
How do you monitor brand deals over time?
Sponsorship activity is not static — a creator with zero sponsored posts last month can pick up several new deals this month, and a brand can rotate its spend from one creator to another. Monitoring means re-running the same creator list on a schedule and comparing each run's output, rather than treating a single scan as the whole picture.
The Actor itself only rolls up deals within a single scan — sponsorDealCountInRun, isRepeatSponsor, sponsorFirstPostTimestamp and sponsorLastPostTimestamp describe what happened inside that run's scanned window, not across separate runs, since the Actor keeps no state between runs. The comparison across time therefore happens in your own pipeline: keep each run's resolvedBrandUsername, sponsorshipEvidence and sponsoredEngagementIndex values, then diff them against the previous run — a brand handle that appears in resolvedBrandUsername for the first time is a new deal, and a rising sponsoredEngagementIndex shows sponsored content starting to underperform (or outperform) a creator's organic baseline.
A practical loop: schedule a weekly run across your watch-list of creators with Apify's Schedules feature, store each run's rows in your own database or a second Apify dataset, and alert when a new resolvedBrandUsername shows up, when sponsorDealCountInRun for a known brand increases, or when a post's isPaidPartnership and hasCaptionAdSignal disagree on a creator you're actively monitoring for disclosure compliance.
Integrate Instagram Post Scraper (Sponsored Post Finder) and automate your workflow
Instagram Post Scraper (Sponsored Post Finder) works with any language or tool that can send an HTTP request — it's an Apify Actor, reachable through the Apify API and every official Apify client library.
REST API with Python
import requestsTOKEN = "<YOUR_APIFY_TOKEN>"url = f"https://api.apify.com/v2/acts/instagram-post-scraper-sponsored-post-finder/run-sync-get-dataset-items?token={TOKEN}"payload = {"username": ["mkbhd", "https://www.instagram.com/natgeo/"],"sponsorshipFilter": "anySponsorshipSignal","resultsLimit": 20,}response = requests.post(url, json=payload)rows = response.json() # primary result array: one post row per itemfor row in rows:print(row["ownerUsername"], row["resolvedBrandUsername"], row["sponsorshipEvidence"])
Scheduled monitoring and delivery
There is no dedicated webhook payload built into this Actor, but Apify's platform-level Schedules run it on a cron expression against a fixed creator list, and platform webhooks (Console → Integrations → Webhooks) can notify your endpoint whenever a scheduled run finishes so a downstream job can pull the fresh dataset. For a simpler setup, poll the Apify API for the latest run's dataset on your own interval instead.
Is it legal to scrape Instagram posts and sponsorship data?
Yes — scraping publicly accessible data is generally lawful when it targets content any logged-out visitor can already see, which is what this Actor reads: no login, no session, no private profiles. In the United States, courts have held that accessing data available to any visitor without bypassing an access control does not violate the Computer Fraud and Abuse Act (hiQ Labs, Inc. v. LinkedIn Corp., 9th Cir. 2019). Because the output includes personal and business data — creator usernames, sponsor brand handles, follower counts, captions — data-protection regimes such as GDPR (EU) and CCPA (California) can govern how you store, process and retain it, separately from whether the initial scrape was lawful, and Instagram's own Terms of Use separately restrict automated access as a contractual matter. Scraping for internal brand-safety monitoring generally carries a different risk profile than scraping to train a model on individuals' content. Consult your legal team for commercial use cases involving bulk storage of creator or sponsor personal data.
Frequently asked questions
Which languages does the caption ad-cue vocabulary cover?
The built-in phrase and hashtag list is mostly English (#ad, #sponsored, #paidpartnership, "paid partnership", "sponsored by", "use code", "promo code", and more), plus a handful of non-English markers: German (werbung, anzeige), Spanish (publicidad). There's no extraAdKeywords-style input to extend the vocabulary yourself in this Actor — the list is fixed in the Actor's code.
What's the difference between resultsLimit and maxPostsToScan?
resultsLimit is how many rows you get back and pay for per creator (default 10). maxPostsToScan is how deep the Actor looks while filtering (default 300), and it only matters once a sponsorship filter, brand allow-list, or follower threshold is active — with no filter on, the Actor stops as soon as resultsLimit rows are collected, no matter how high maxPostsToScan is set.
How does Instagram Post Scraper (Sponsored Post Finder) handle Instagram's anti-bot measures?
Every feed and post-page request retries up to 3 times with an increasing delay, rotating to a fresh Apify Proxy session on each retry (except the last). Requests use browser-realistic headers, and the feed connection is capped at 10 concurrent connections (5 per host) to avoid overwhelming a single proxy exit. A CSRF token and numeric app ID are harvested from the target profile's own HTML before the first feed request, since Instagram's feed endpoint rejects requests without them.
Does Instagram Post Scraper (Sponsored Post Finder) extract sponsored posts and named brand deals?
Yes — every post row carries isPaidPartnership (Instagram's official label), the full sponsor object (sponsorUsername, sponsorFullName, sponsorFollowerCount, and more) when Instagram names a brand, hasCaptionAdSignal/captionAdSignals for caption-based cues, and resolvedBrandUsername/resolvedBrandConfidence for the brand the Actor is confident about. resolvedBrandUsername is null whenever a post is only caption-flagged with no official tag — caption cues alone are never enough to name a brand.
How many results does it return per creator?
Up to resultsLimit rows per creator (default 10, schema maximum 100000), drawn from up to maxPostsToScan posts inspected (default 300, schema maximum 5000). A single post/reel/tv URL always returns exactly one row and doesn't count against either budget.
Am I charged for posts that get filtered out or fail?
No. Per this Actor's own published pricing configuration, the row_result charge ($0.002) fires only for a row that is actually saved to the dataset — posts scanned but excluded by sponsorshipFilter, sponsorUsernames, or minSponsorFollowerCount, and posts that fail to load, are never pushed to the dataset and never charged.
How do I monitor a creator's or brand's sponsorship activity over time?
Schedule a recurring run across the same creator list with Apify's Schedules feature, and diff resolvedBrandUsername, sponsorDealCountInRun and sponsoredEngagementIndex against your own stored copy of the previous run's rows — see "How do you monitor brand deals over time?" above for the full loop. The Actor itself keeps no history between runs.
Does it work with Claude, ChatGPT, and AI agent frameworks?
It's callable as an HTTP endpoint through the Apify API by any agent framework that can issue a request and read JSON back — start a run, poll or await its dataset, and pass sponsorshipEvidence and the resolved-brand fields to your model as grounded, current context. No dedicated MCP server is documented for this Actor.
How does Instagram Post Scraper (Sponsored Post Finder) compare to other Instagram scrapers?
As observed on their own Apify Store listings on 2026-07-30: scrapemint's Instagram Influencer Analyzer & Sponsored Post Tracker documents a single isSponsored boolean plus a sponsorSignals array that flags #ad/#sponsored/partnership labels together, without separating Instagram's official tag from a caption cue, and without a brand-follower-count filter or a repeat-deal rollup. Apify's own Instagram Post Scraper lists "Is it a sponsored post?" and "Is it a paid partnership?" among its extractable fields, but its published sample output and field table don't show a sponsor-identity object, caption ad-cue detection, or brand inference. Apify's Export Instagram Comments and Posts Tool exposes only a plain isSponsored boolean in its sample output, with no sponsor identity or caption-signal detection at all. This Actor is the only one of the three, as observed on that date, that reports the official flag and caption cue as separate fields and resolves them to a confidence-labelled brand handle.
Can I use it without managing proxies or an Instagram login?
Yes. No Instagram username, password, or session cookie is ever requested — the Actor authenticates each request with a CSRF token and app ID it harvests itself from the target's public profile page. A residential Apify Proxy group is pre-filled by default and recommended for reliability at volume; you can swap in a different proxy group or turn proxying off entirely to run direct.
What happens if a profile is private, or a target returns no posts?
A private profile, an empty feed, and a rejected URL form (Instagram tab paths like /stories/, /explore/, or /reels/ without a shortcode aren't treated as usernames) are each logged with their specific reason and that target is skipped — the run continues with the remaining creators. The whole run only fails if every target produces zero scanned posts; if some posts were scanned but none matched your sponsorship filter, the run finishes normally with a status message suggesting you raise maxPostsToScan.
💬 Your feedback
Found a bug, or need a sponsorship field this Actor doesn't expose yet? Open an issue on the Actor's Issues tab in Apify Console, or leave a review on the Store listing — it goes straight to the people maintaining it.