Third-Party Data Vendors

Every Apify actor and Bright Data dataset the Content Agent Dashboard pays for. Prices are BRONZE-tier rates read from the Apify API; speeds and bills are measured from real runs.

30Apify actors
8BD datasets
10free / local
$0.40total test spend
7stale rates

How to read this

The dashboard scrapes nothing itself. It rents every fetch. Each tab is one platform and carries the same four sections, in the same order: Current flow (what runs today, with links) → Misconceptions (what is wired but never used, and where the recorded price is wrong) → Actors and data sets (the full table) → Flow diagrams (current and suggested, each carrying price and data limits).

Status is what the code does, which is not always what the registry says. apidojo/tweet-scraper shows as live-and-hardcoded while xquik shows as replies-only, even though the registry names xquik primary for both. That gap is the point of several tabs.

ShapeWhat it isWho billsCount
ActorA rented scraper program on Apify. Send a URL, get rows, pay per row. Lives at apify.com/<slug>Apify30
DatasetBright Data's equivalent, addressed by an id like gd_lkaxegm826bjpoo9m5 against one endpoint. No public page exists per datasetBright Data8 (4 wired)
ProxyBright Data Web Unlocker — a residential fetch with JS rendering, used when a plain request is blockedBright Data1
Free / localPublic feeds, oEmbed, RSS, and two programs running on your own servernobody10

Two account facts that change every price here: the Apify plan is BRONZE, measured rather than assumed, and tiered per-event pricing means the same actor costs a different amount on a different plan. Bright Data datasets bill per returned row with no per-run object to read a bill from, so their cost is rows × rate rather than a settled figure.

Every vendor, all platforms

What the status words mean

Status describes what the code actually does, which is not always what the registry says. Several vendors are registered and configured but can never be reached.

StatusWhat it means
live Runs in normal operation and we are billed for it
live — 302 of 310 Runs, and the numbers say how much of the stored data it actually brought in. Where two vendors share a job, this shows which one is really doing the work
live, primary First choice for this job, and it genuinely is the one that runs
live — hardcoded Runs because its web address is typed directly into the code. The tier chooser is asked which actor to use and its answer is ignored, so the registry's choice has no effect
fallback Second in line. Only runs if the first choice fails — in practice, rarely or never
unreachable Registered as a backup but cannot ever run. Either the code only ever reads the first choice in the list, or the primary's address is hardcoded so no fallback is consulted. Listed, but decoration
disabled revert copy A switched-off copy of an actor we stopped using, kept so we could go back to it if the replacement went badly. Deliberately inert — it cannot run and costs nothing
never wired Available on the vendor's side and sometimes already format-checked, but no code calls it. Its real rate is unknown because it has never run
CLI only, never run Reachable only by typing a command by hand. No scheduled job or dashboard button triggers it
free A public feed, an official API within its free quota, or a program on our own server. No vendor, no bill

How the prices work

Almost no vendor charges one flat price. A single run can combine four different charges, and our registry can only record the first of them — which is why the Extra charges & limits column below matters as much as the rate.

Kind of chargeWhat it meansWorst example here
Per item Charged for every row that comes back — one post, one comment, one follower, one ad. This is the only kind our registry can record apify/facebook-pages-scraper at $0.0082 a page
Start fee A flat charge every time the job runs, before any data arrives. Splitting one sweep into many small runs pays it many times over data_xplorer/tiktok-ads-library-fast at $0.025 per run
Minimum The smallest amount you are allowed to ask for. You pay for that many even when fewer exist — a quiet account still bills the full minimum X followers: 200 people minimum · Threads: 10 posts
Overshoot The vendor sends back more than you asked for and bills for all of it. Not a minimum — you asked for a small number and were charged for a larger one One tweet billed as 15 rows (≈$0.0033, not $0.00022)
Conditional charge An extra fee triggered by an option you turned on — a date filter, an email lookup, profile enrichment — or even by a run that finds nothing LinkedIn no-result: $0.001 for an empty run

The full list

VendorPlatformJobStatusPer itemExtra charges & limits
apify/instagram-scraperInstagramposts, post detail, commenter profileslive$0.0023—
apify/instagram-profile-scraperInstagramprofile + 12 posts freelive$0.0023optional extra account detail +$0.006
scrapesmith/instagram-comments-scraperInstagramcommentslive$0.0005
per comment
start fee $0.00005
scraping_solutions/instagram-scraper-followers-following-no-cookiesInstagramfollowers / followinglive$0.0007
per person
minimum 25 people
apify/instagram-post-scraperInstagramposts backupunreachable$0.0015primary's address is hardcoded, so this never runs
datadoping/instagram-followers-scraperInstagramfollowersdisabled revert copy$0.0014rate is in the adapter, not the registry
apify/instagram-comment-scraperInstagramcommentsdisabled revert copy$0.0023—
gd_lkaxegm826bjpoo9m5Facebookpage postslive — 7 of 310$0.0015
per post
40.5 s — too slow to lead, so it rarely runs
apify/facebook-posts-scraperFacebookpage postslive — 302 of 310$0.004
per post
start fee $0.001 · +$0.001 when a date filter is used
apify/facebook-pages-scraperFacebookpage + personal profilelive$0.0082
per page
registry records $0.00246 — 3.3× under
apify/facebook-comments-scraperFacebookcommentslive$0.002
per comment
start fee $0.001 · +$0.001 when a filter is used
danek/facebook-posts-fastFacebookone post by URLlive$0.00233
per post
start fee $0.00005
danek/facebook-posts-share-scraperFacebookresharerslive$0.00167
per person
start fee $0.00005 · overshoots — asked 10, billed 12
apify/facebook-ads-scraperMeta adsad librarylive$0.005
per ad
—
gd_lkay758p1eanlolqw8Facebookcommentsnever wired—never run, so the rate is unknown
apidojo/tiktok-scraperTikTokposts + profile free, post detaillive$0.0003
per post
cheapest post source anywhere here
gd_l1villgoiiidt09ciTikTokprofile + top postsfallback$0.0015
per profile
returns top posts, not newest — can miss a new post
apidojo/tiktok-comments-scraperTikTokcommentslive$0.0003
per comment
—
clockworks/tiktok-followers-scraperTikTokfollowerslive$0.001
per person
start fee $0.001 — not in the registry · minimum 25
clockworks/tiktok-comments-scraperTikTokcommentsdisabled revert copy$0.001—
data_xplorer/tiktok-ads-library-fastTikTok adsad library, EU/UK onlylive$0.0015
per ad
start fee $0.025 — the largest here · US is rejected
apidojo/tweet-scraperXpostslive — hardcoded$0.0004
per tweet
runs instead of the registry's choice, at 2.67× the price
xquik/x-tweet-scraperXreplies — and posts, per registrylive, replies only$0.00015
per tweet
registry names it first choice for posts too; the code overrides that
kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapestXone tweetlive$0.00022
per row
overshoots badly — 1 tweet bills 15 rows ≈ $0.0033
kaitoeasyapi/premium-x-follower-scraper-following-dataXfollowerslive$0.00015
per person
minimum 200 people — biggest line in the ledger, $3.77 of $9.55
api-ninja/x-twitter-replies-retweets-scraperXretweeterslive$0.00035
per person
start fee $0.01 · must set category: 'retweets' or it returns repliers
apidojo/twitter-replies-scraperXreplies backupunreachable$0.0004
per item
+$0.014 per query · comment layer has one fixed actor per platform
seemuapps/x-tweet-retweeters-scraperXretweeters backupunreachable$0.0015code only ever reads the first choice
khadinakbar/x-tweet-engagement-scraperXreplies + quotes + retweetsunreachable$0.006third in a list that is never read past the first
seemuapps/x-quote-tweets-scraperXquote tweetsCLI only, never run$0.003no scheduled job or button triggers it
data_direct/twitter-tweet-quotes-scraperXquotes backupunreachable$0.006—
gd_lwxkxvnf1cynvib9coXone tweet by URLnever wired—cannot list an account's tweets, so it serves no capability
YouTube channel RSSYouTubenewest videoslive — cap 15$0public feed holds only 15 videos — the cap that pushes first pulls to paid
YouTube Data API v3YouTubelikes, comment countslive$0free quota of 10,000 units a day · needs YOUTUBE_API_KEY
streamers/youtube-channel-scraperYouTubedeep pull + channel statslive — 197 of 207$0.001
per video
returns no like counts at all
streamers/youtube-comments-scraperYouTubecommentslive$0.0015
per comment
registry records $0.004 — 2.7× over
gd_lk56epmy2i5g7lzu0kYouTubeone video by URLnever wired—cannot list a channel's videos
harvestapi/linkedin-company-postsLinkedIncompany postslive$0.002
per post
start fee $0.00005 · $0.001 even when it finds nothing · floor of 8 · optional comment/reaction bundles $0.002 each
gd_l1vikfnt1wgvvqz95wLinkedIncompany profilelive, primary$0.0015
per profile
cheaper than the Apify fallback, and genuinely runs first
harvestapi/linkedin-companyLinkedIncompany profilefallback$0.004
per profile
start fee $0.00005
gd_l1viktl72bvl7bjuj0LinkedInperson profilelive, primary$0.0015
per person
—
harvestapi/linkedin-profile-scraperLinkedInperson profilefallback$0.004
per person
$0.01 if an email is requested — 2.5× more
harvestapi/linkedin-post-commentsLinkedIncommentslive$0.002
per comment
registry records $0.004 — 2× over · optional profile enrichment $0.002–$0.01
apimaestro/linkedin-post-detailLinkedInone postlive$0.005
flat per post
—
datadoping/linkedin-post-repost-scraperLinkedInresharerslive$0.0014
per person
minimum 10 — fewer is rejected outright
apimaestro/linkedin-post-resharesLinkedInresharers backupunreachable$0.005second in a list read only to the first
benjarapi/linkedin-company-postsLinkedInposts backupunreachable$0.002primary's address is hardcoded
data_xplorer/linkedin-ad-library-scraperLinkedIn adsad librarylive$0.001
per ad
registry records $0.0005 — 2× under
gd_lyy3tktm25m4avu764LinkedInone post by URLnever wired—cannot list an account's posts
futurizerush/meta-threads-scraperThreadsposts + full profile freelive — no fallback$0.0025
per post
start fee $0.005 · minimum 10 posts · overshoots — a 10-post ask billed $0.045, which is 16 posts
automation-lab/google-ads-scraperGoogle adsad librarylive$0.001
per ad
start fee $0.005 per run · the ad limit applies per advertiser, not per run
tesseract.jsGoogle adsOCR the creativelive — only copy source$0runs on our own server — no vendor, no key
Bright Data Web Unlockerallrescue fetch when blockedlive$0.0025
per fetch
—

Test spend, and the rates that have drifted

Every figure in this document came from a real run billed to the account. Total: $0.40.

PlatformWhat was runData limit appliedCost
Instagramprofile, posts, apidojo candidate — twice, on two accounts12 posts per run$0.0716
FacebookBright Data posts, pages-scraper, Apify posts5 posts, 1 page$0.037
TikTokposts10 posts$0.003
Xapidojo vs xquik, same account10 tweets each$0.0056
YouTubefree RSS + API, paid actor12 videos$0.012
LinkedInposts with bundle switches on10 posts, 5 comments, 5 reactions$0.118
Threadsposts10 posts — the hard minimum$0.045
Google Adsads by advertiser id · ad-text comparison across 3 actors5–10 ads per run, 4 advertisers$0.039
Total$0.40

The LinkedIn line is the expensive one because turning the bundle switches on turned a 10-post request into 59 billed rows. That is the finding, not an accident.

Seven rates the registry has wrong

The registry (scripts/lib/provider-tiers.js) is what the Capability Explorer quotes from and what the budget guard reserves against. These seven no longer match the bills.

VendorRegistryActualDirection
apify/instagram-scraper$0.004$0.0023over-quotes by 74%
apify/instagram-post-scraper$0.0023$0.0015over-quotes
apify/facebook-pages-scraper$0.00246$0.0082under-quotes 3.3×
streamers/youtube-comments-scraper$0.004$0.0015over-quotes 2.7×
harvestapi/linkedin-post-comments$0.004$0.002over-quotes 2×
data_xplorer/linkedin-ad-library-scraper$0.0005$0.001under-quotes 2×
clockworks/tiktok-followers-scraper$0.00102$0.001 + $0.001 startstart fee missing
The two under-quotes are the ones that bite. Over-quoting only makes the Explorer look expensive; under-quoting means the budget guard reserves too little and a run can exceed a cap it believed it was inside.

The registry has no way to record a start fee

provider-tiers.js can record a price per item and nothing else — there is no field for a flat charge. But twelve actors charge one every time they run, and none of those fees has ever reached an estimate.

ActorCharge to startAlso charges
data_xplorer/tiktok-ads-library-fast$0.025—
api-ninja/x-twitter-replies-retweets-scraper$0.01—
automation-lab/google-ads-scraper$0.005—
futurizerush/meta-threads-scraper$0.005—
apify/facebook-posts-scraper$0.001filter-applied $0.001
apify/facebook-comments-scraper$0.001filter-applied $0.001
clockworks/tiktok-followers-scraper$0.001—
harvestapi/linkedin-company-posts$0.00005no-result $0.001
harvestapi/linkedin-company$0.00005—
scrapesmith/instagram-comments-scraper$0.00005—
danek/facebook-posts-fast$0.00005—
danek/facebook-posts-share-scraper$0.00005—

Two of these deserve attention beyond the missing field. filter-applied means using a date filter costs money, and no-result means you are billed when a run comes back empty.

The registry also disagrees with itself

apify/instagram-scraper is recorded at $0.004 on lines 85, 167 and 191, and at $0.0023 on line 462 — in the same file. Which price the Explorer shows depends on which job you ask about. The real price is $0.0023, so three of the four entries are wrong.

The four biggest wins, across all platforms

PlatformChangeEffect
InstagramRead the 12 posts already inside the profile reply instead of buying them again$0.0299 → $0.0023, 15.5 s → 4.2 s
XDelete the hardcoded actor URL and let the resolver pick xquik2.5× cheaper, 2× faster, one vendor instead of two
YouTubePage the free RSS feed past 15 and enrich paid rows with the Data API toofree, 15× faster, fills likes which the paid actor leaves empty
Google AdsBatch all 17 advertiser ids into one run$0.005 once instead of $0.085

Current flow

Five jobs, four actors — apify/instagram-scraper is used twice for two different purposes.

A routine refresh makes two calls in sequence. First apify/instagram-profile-scraper is asked {"usernames":[handle]} and returns the profile — and 12 complete posts inside the same reply. Then apify/instagram-scraper is asked for posts and buys those same posts again. That is the whole story of this tab.

Comments come from scrapesmith/instagram-comments-scraper, which needs post URLs and therefore cannot run until posts exist. Commenter profiles then need usernames from the comments, so the chain is three deep: posts → comments → commenter profiles. Followers come from scraping_solutions/instagram-scraper-followers-following-no-cookies and need only the handle.

Bright Data serves nothing on Instagram except the Web Unlocker, which rescues a blocked single-post fetch.

Misconceptions

We buy the same 12 posts twice, every single refresh
Who said it
The registry file says apify/instagram-scraper is "the only tested actor returning videoUrl, hashtags, mentions, paidPartnership and childPosts together". So the code asks the profile actor for the profile, then asks the posts actor for the posts.
What I found
I asked the profile actor about one account. It sent back the profile and 12 whole posts in the same reply — and 8 out of 8 videos had a working video link. Then I asked the posts actor for the same account. It sent back the exact same 12 posts. I checked by comparing every post's ID one by one. We were paying for them a second time.
Action: get posts · Actor: apify/instagram-scraper · $0.0276 → $0.0023 12× less · 15.5 s → 4.2 s
The price we have written down for posts is almost double the real one
Who said it
The registry says Instagram posts cost $0.004 each.
What I found
They cost $0.0023. I checked this two different ways: Apify's own price list said $0.0023, and a real bill for 12 posts came to $0.0276, which works out to $0.0023 each. So the Explorer shows a price 74% too high for every Instagram posts job. It also writes the price down twice in the same file — $0.004 in three places and $0.0023 in one — so the number you see depends on which job you ask about.
Action: quote a posts job · Actor: apify/instagram-scraper · quoted $0.004 → real $0.0023 74% over
The "cheap backup" is now the cheapest one, and it can never run
Who said it
The registry marks apify/instagram-post-scraper as a fallbackOnly backup, because back then $0.0023 was cheaper than $0.004.
What I found
The prices have swapped around. The backup is now $0.0015 and the main one is $0.0023 — so the backup is the cheaper of the two, which is the opposite of what the flag was written for. It does not matter in practice, because pull-data.js line 38 writes the main actor's web address straight into the code. The chooser never gets asked, so this backup has never run and cannot run.
Action: pick a posts actor · Actor: apify/instagram-post-scraper · $0.0015 unreachable · registry says $0.0023
Nothing is running behind our back
Who said it
The name datadoping appears in the follower code, which makes it look like a second follower actor is running alongside the official one.
What I found
It is not. It is called DISABLED_instagram_datadoping — a switched-off copy kept so we could go back to it if the swap on 22 Aug 2026 went badly. It cannot run. Its $0.0014 price is written in the adapter but not in the registry, which is the real (small) problem: if you ever wanted to switch back, the Explorer could not price it.
Action: none needed · Actor: datadoping/instagram-followers-scraper · $0 — it never runs
The much cheaper actor is cheaper because it leaves out something we need
Who said it
A cheaper competitor, apidojo/instagram-scraper, is about 4.7× cheaper, so it looked like an easy saving.
What I found
I paid for a real run to check. It does return video links on 8 of 8 videos, and the like counts match. But it returns no view count on any post at all — and we store view counts. It also gives every field a different name, so the code that reads the answer would have to be rewritten. Turned down because of missing data, not price.
Action: replace posts actor · Actor: apidojo/instagram-scraper · rejected · would lose views
Looking up a commenter costs nearly twice what it should
Who said it
Nobody wrote this down — it is just how pull-commenter-profiles.js was built. It calls the posts actor in details mode and records $0.004 per person looked up.
What I found
The profile actor gives back the same information about that person for $0.0023. It is the same job, the same answer, from a cheaper actor we already pay for and already use on this platform.
Action: look up a commenter · Actor: apify/instagram-scraper → apify/instagram-profile-scraper · $0.004 → $0.0023 43% less

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
apify/instagram-scraper "Instagram Scraper"live — posts, post detail, commenter profiles
Inputan account handle or post links, plus how many posts to fetch. A second mode takes a username to look up one person.
ReturnsPost details — caption, likes, comment count, views, video link, hashtags, location and the owner, one row per post.
idshortCodeurltypecaptiontimestamplikesCountcommentsCountvideoUrlvideoViewCountvideoPlayCountvideoDurationdisplayUrlimageschildPostshashtagsmentionstaggedUsersmusicInfoaudioUrlproductTypepaidPartnershipcoauthorProducerslocationIdlocationNamealtownerIdownerUsernameownerFullNamefirstCommentlatestCommentsisCommentsDisabledisPinneddimensionsWidth/HeightoriginalWidth/Height hashtags — tags and entity_tags tables are both 0 rows; keywords are rebuilt from caption text instead · musicInfo — no column, and it is what makes a Reel travel · productType — no column, so a Reel cannot be told from a feed post · taggedUsersmentionsaudioUrlaltownerFullNameownerIdisCommentsDisabledisPinneddimensions*original*locationId — no columns · firstComment / latestComments — ignored because comments are bought separately shares, bookmarks_count, reactions, thread_id, posting_tool, topic_tag — all 0/482. Instagram publishes none of them $0.0023/item
registry says $0.004
apify/instagram-profile-scraper "Instagram Profile Scraper"live — profile
Input{"usernames":["handle"]} — just the account name.
ReturnsProfile details — followers, following, post count, bio, verified tick, business category, external links — and the 12 most recent posts in full.
idusernamefullNamebiographyfollowersCountfollowsCountpostsCountverifiedprivateisBusinessAccountbusinessCategoryNamebusinessAddressexternalUrlexternalUrlsexternalUrlShimmedfbidprofilePicUrlprofilePicUrlHDhighlightReelCountigtvVideoCountlatestIgtvVideosjoinedRecentlyrelatedProfileslatestPosts[12] latestPosts[12] — twelve complete posts with video, views, hashtags, taggedUsers and productType, discarded on every refresh · relatedProfiles — Instagram's own "similar accounts", free competitor discovery · businessCategoryNamebusinessAddresshighlightReelCountigtvVideoCountlatestIgtvVideosjoinedRecentlyfbidprofilePicUrlHDexternalUrlsprivate contact_email, contact_phone, country_code — 0/10. Not in this actor's output $0.0023/profile
+$0.006 optional about-account
scrapesmith/instagram-comments-scraper "Instagram Comments Scraper"live — comments
Inputthe web address of a post, plus how many comments to fetch.
ReturnsComment details — the text, when it was written, likes, reply count, nested replies, and who wrote it (name, verified, private, picture).
commentIdtextusernameuserFullNameuserIdownerownerUsernameownerProfilePicUrltimestamp (unix)likesCountrepliesCountchildCommentCountrepliesisVerifiedisPrivateisMentionablehasLikedCommentmediaTypemediapostIdpostUrlcommentUrl replies — nested reply objects arrive free; parent_platform_comment_id and threading_depth columns exist and are 0/123, so reply threads are bought and thrown away · hasLikedCommentisMentionablemediamediaType · owner / postId are duplicates of fields already kept account_type (0/123), shares, is_post_author — not in this actor's output $0.0005/comment
+$0.00005 start
scraping_solutions/instagram-scraper-followers-following-no-cookies "Instagram Followers/Following Scraper | No Login | No Cookies"live — followers and following
Inputan account handle and a direction — followers or following.
ReturnsA list of people — username, full name, private and verified flags, profile picture. Identity only: no bio, no follower counts.
idusernamefull_nameis_privateis_verifiedprofile_pic_urltypeusername_scrape — 8 fields total type and username_scrape are echoes of your own request, not data The big gap. bio, followers_count, following_count, posts_count, location, account_created_at are all 0/45 — the actor sends none of them. Filling them needs a profile call per follower: about $58 for 25,000 $0.0007/person
min 25
apify/instagram-post-scraper "Instagram Post Scraper"unreachable — registered as a backup, but pull-data.js hardcodes the primary
Inputaccount handles or post links.
ReturnsPost details, but without the video link — which is why it was kept as a backup only.
posts, without videoUrl — (never runs)— $0.0015/post
registry says $0.0023
datadoping/instagram-followers-scraper "Instagram Followers Scraper (No Cookie)"disabled revert copy — DISABLED_instagram_datadoping
Inputan account handle.
ReturnsA follower list — 6 fields only: id, username, full name, private, verified, picture. Followers only — it cannot list who an account follows.
idusernamefull_nameis_privateis_verifiedprofile_pic_url — (ran once, 45 rows) followers only — no following direction at all $0.0014/person
2× the live actor; rate is in the adapter, not the registry
apify/instagram-comment-scraper "Instagram Comments Scraper"disabled revert copy — DISABLED_instagram_apify
Inputthe web address of a post.
ReturnsComment details, but without the commenter's verified flag, private flag or profile picture.
comments, without isVerified / isPrivate / profile picture — (never runs)—$0.0023/comment
TOTAL — measured test spend6 runs across 2 accounts, both rounds Limits applied: 12 posts per run, 1 profile per run$0.0716

Flow diagrams

current 4 steps, step 2 redundant

A routine incremental refresh of one Instagram account.

1
Step: fetch the account profile
What this isapify/instagram-profile-scraperApify actor
“Instagram Profile Scraper” — a rented scraper program. You give it a username, it hands back that account’s details — follower count, bio, verified tick — and its 12 most recent posts, at no extra charge.
{"usernames":["rollersoftware"]} → profile + latestPosts[12], complete with videoUrl on 8/8 videos
$0.00234.2 s1 profile
2
Step: buy the posts (the redundant one)
What this isapify/instagram-scraperApify actor
“Instagram Scraper” — a different rented program that fetches an account’s posts. It is the dearer of the two and returns posts we were already given free in step 1.
Identical shortCode set to step 1. This is the entire overspend.
$0.027611.3 s12 posts
3
Step: fetch comments on those posts
What this isscrapesmith/instagram-comments-scraperApify actor
“Instagram Comments Scraper” — you give it the web address of a post, it returns the comments under it with each commenter’s name. It cannot start until posts exist.
Needs post URLs from step 2 — cannot start until posts exist
$0.0005/comment+$0.00005 start
4
Step: look up each commenter
What this isapify/instagram-scraperApify actor
“Instagram Scraper” — the same posts program, run in a second mode that looks up a person instead. It charges $0.004 per person when the profile program does the same job for $0.0023.
pull-commenter-profiles.js calls instagram-scraper in details mode
$0.004 each3 chains deep
5
Step: fetch the follower list
What this isscraping_solutions/instagram-scraper-followers-following-no-cookiesApify actor
“Instagram Followers/Following Scraper | No Login | No Cookies” — give it a username and it lists the people who follow that account. It needs nothing from the other steps, so it can run on its own.
Needs only the handle, runs independently
$0.0007/personmin 25
Posts path: $0.0299 · 15.5 s for 12 posts + 1 profile.

Field check — does the suggested flow lose anything?

Comparing the two live runs key by key, the bundle holds 14 of the 17 fields the dashboard stores. Every "how often" number below is counted straight from the database. The three gaps and their answers:

Missing from bundleStored asHow often (DB-verified)Answer
paidPartnershipis_paid_partnership 481/482 confirmed No call needed — the bundle leaves the field out when the answer is "no". Treat missing as false
videoDurationduration_seconds 103/482 confirmed Top-up branch, only on a new video post. Skip the branch and you lose 103 rows
coauthorProducerscoauthor_handles 14/482 (3%) confirmed Top-up branch, only on a new collab post. Skip the branch and you lose 14 rows

So the honest claim is one call covers every stored field on about 97% of posts, with a rare second call for the rest — provided the two top-up branches are actually built. Leave them out and the saving is real but 117 rows of data stop being collected.

One thing to know about views: it is filled on only 102 of 482 Instagram posts, because Instagram publishes a view count for videos only — and there are 103 videos. That does not change the decision to reject apidojo, which returned no view count on any post, video or not.

Current flow

Seven jobs across two vendors — the only platform where Bright Data and Apify compete for the same work.

Posts have two tiers. The registry names Bright Data's gd_lkaxegm826bjpoo9m5 primary at $0.0015, with apify/facebook-posts-scraper as the fallback. In practice the fallback does almost everything — 302 of 310 stored posts — because Bright Data takes 40.5 s against Apify's 5.3 s.

The page profile is a separate paid call to apify/facebook-pages-scraper: it is the only source of an exact follower count, and it returns no posts, so there is no Instagram-style bundle to exploit here.

Comments come from apify/facebook-comments-scraper and need post URLs from the posts job. One post by URL goes to danek/facebook-posts-fast, resharers to danek/facebook-posts-share-scraper, and the Meta ad library to apify/facebook-ads-scraper.

Misconceptions

The vendor we call "first choice" does almost none of the work
Who said it
The registry names Bright Data's gd_lkaxegm826bjpoo9m5 as the first choice for Facebook posts, with the Apify actor as the backup.
What I found
I counted where our stored posts actually came from. Bright Data brought in 7 posts. The "backup" brought in 302. The reason is speed: Bright Data takes 40.5 seconds and Apify takes 5.3, so the system gives up on the first choice and uses the backup nearly every time. That means every price estimate we show is based on a vendor that handles 2% of the work.
Action: get page posts · Actor: gd_lkaxegm826bjpoo9m5 (quoted) vs apify/facebook-posts-scraper (actually used) · quoted $0.0015 → really $0.004 + $0.001 3.3× under
The page-profile actor costs more than three times what we think
Who said it
The registry says apify/facebook-pages-scraper costs $0.00246 per page.
What I found
I ran it once on a real page and the bill was $0.0082. That is 3.3× more than written down. This one matters more than it looks: it is an under-estimate, so the spending guard sets aside too little money and a job can quietly go over a limit it thought it was under.
Action: get page profile · Actor: apify/facebook-pages-scraper · quoted $0.00246 → real $0.0082 3.3× under-quoted
Comment counts are missing because the actor stopped sending them
Who said it
The registry note says the Apify posts actor "includes topComments".
What I found
It does not any more. A real run came back with no comment field of any kind — not comments, not commentsCount, not topComments. That explains a number that looked like a bug: comments_count is filled on only 69 of 310 Facebook posts. The 7 Bright Data posts all have it; nearly all the Apify ones do not.
Action: get comment counts · Actor: apify/facebook-posts-scraper · no extra cost · the note is simply out of date
The Instagram trick does not work on Facebook — the free numbers are rounded off
Who said it
This was my own idea: Bright Data sends nine page details free alongside posts, so maybe the separate $0.0082 page call could be deleted, exactly like the Instagram saving.
What I found
It does send them free — but the free follower number came back as 10,000 when the page really has 10,895. It is rounded to the nearest ten thousand. You cannot track whether an account is growing with a number like that, so the paid call has to stay. The idea did not survive the test.
Action: delete the page call · Actor: apify/facebook-pages-scraper · saving rejected · would lose exact follower counts
We pay for numbers on every row and then throw them away
Who said it
Nobody — this is a gap between what arrives and what gets saved.
What I found
Bright Data sends video_view_count and count_reactions_type on every single row, and nothing in our code reads them, so those columns stay empty on that path. The pages actor sends whether a page is verified, and is_verified is empty for all 11 accounts. We already paid for all of it.
Action: save views, reactions, verified · Actor: both Facebook actors · $0 — already paid for
Using a date filter costs extra, and nobody wrote that down
Who said it
Nothing in the registry — it can only record a price per item.
What I found
Both apify/facebook-posts-scraper and apify/facebook-comments-scraper charge an extra $0.001 every time a filter is applied, on top of a $0.001 charge just for starting. Our registry has no place to record either kind of fee, so neither has ever appeared in an estimate.
Action: run with a date filter · Actor: apify/facebook-posts-scraper · +$0.001 filter +$0.001 start never quoted
A ready-made comments dataset is sitting unused
Who said it
Nobody — it was set up and then forgotten.
What I found
gd_lkay758p1eanlolqw8 (Bright Data "Facebook Comments") holds full details about who commented, and its format has already been checked against our database. No code calls it. So on the rare runs where Bright Data fetches the posts, no comments come along with them.
Action: get comments on the Bright Data path · Dataset: gd_lkay758p1eanlolqw8 · never run — rate unknown

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
gd_lkaxegm826bjpoo9m5Bright Data — "Facebook — Pages Posts by Profile URL" served 7 of 310 declared primary
no public page; api.brightdata.com/datasets/v3/scrape
Inputa Facebook page's web address and how many posts to fetch.
ReturnsPost details — text, date, likes by type, comment and share counts, video views, attachments — plus 9–12 page profile fields free (followers, category, email, phone, website).
44 keys. Post: post_idurlcontentdate_postednum_commentsnum_sharesnum_likes_typevideo_view_countcount_reactions_typeattachmentshashtagsis_sponsored Page: page_followerspage_is_verifiedpage_emailpage_phonepage_categorypage_external_websitepage_namepage_intropage_creation_timepage_logopage_price_rangepage_reviews_score video_view_count and count_reactions_type — on every row, never mapped, so views and reactions are 0/7 · all 9–12 page_* fields — the page profile arrives free and is discarded Exact follower counts — page_followers is rounded (10,000 vs a real 10,895) $0.0015/post
40.5 s
apify/facebook-posts-scraper "Facebook Posts Scraper"live — the de-facto primary, 302 of 310
Inputa Facebook page's web address and a post limit.
ReturnsPost details — text, time, likes, shares, view counts, reactions, media, whether it is a video. No comment count at all.
postIdtopLevelUrlurltexttimetimestamplikessharesviewsCountvideoPostViewCounttopReactionsCountmediaisVideopaidPartnershipcollaboratorspageNameuserfeedbackIdliveViewerCounttextReferencespageAdLibraryfacebookId collaboratorstextReferencesfeedbackIdliveViewerCountpageAdLibrary — no columns Comment counts. No comments, commentsCount or topComments in the payload — comments_count is 61/302. The registry's "includes topComments" note is out of date $0.004/post
+ $0.001 start
5.3 s
apify/facebook-pages-scraper "Facebook Pages Scraper"live — page and personal profiles
Inputa Facebook page or personal profile address.
ReturnsPage profile details — the exact follower count, likes, category, intro, email, website, messenger, creation date, cover photo. No posts.
followers (10,895 exact)likesemailwebsitewebsitescategorycategoriesintroinfotitlepageIdpageNamepageUrlcreation_datemessengerprofilePictureUrlcoverPhotoUrlad_statusadditionalPropertiespageAdLibraryfacebookId messengercoverPhotoUrlad_statuscategoriesadditionalProperties · verification — is_verified is 0/11 although it is returned Posts — no post array at all, so no bundle exists on Facebook $0.0082/page
registry says $0.00246
8.0 s
apify/facebook-comments-scraper "Facebook Comments Scraper"live — the only Facebook comment source
Inputthe web address of a single post.
ReturnsComment details — text, date, likes, how deeply nested the reply is, and the commenter's name, profile link and picture.
idtextdatelikesCountprofileNameprofileUrlprofilePicturecommentUrlthreadingDepthfacebookIdprofileId threadingDepthfacebookIdprofileId —$0.002/comment
+ $0.001 start
danek/facebook-posts-fast "Facebook Posts Fast"live — one post by URL
Inputpost links passed as direct_urls — as objects, not plain text.
ReturnsOne post in full — total reactions broken down by type, comments, reshares, and video with dimensions.
total_reactions, per-type reaction breakdown, comments, reshares, video with dimensions per-type reaction split — stored only as a total —$0.00233/post
input is direct_urls as objects, not strings
danek/facebook-posts-share-scraper "Facebook Posts Share Scraper"live — resharers, Explorer panel only
Inputthe web address of a post.
ReturnsA list of people who reshared it — names with profile links. Fewer than the share count shows, because most Facebook shares are private.
named resharer accounts with profile links— The true share count — Facebook shares are mostly private, so it returns fewer than posts.shares shows $0.00167 + $0.00005 start
overshoots: asked 10, billed 12
apify/facebook-ads-scraper "Facebook Ads Library Scraper"live — Meta ad library
Inputa page or search term for Meta's public ad library.
ReturnsAd details — the full creative, body text, link, page id, ad format, page like count, call-to-action and display format.
full creative, body text, linkUrl, pageId, ad format, page like count, cta_text, display_format ecommerce-enrichment events—$0.005/ad
gd_lkay758p1eanlolqw8Bright Data — "Facebook — Comments" never wired
Inputthe web address of a post. Never actually called.
ReturnsComment details with full commenter identity. Schema-checked against our database but no code uses it.
full commenter identity— (never runs)——
TOTAL — measured test spend3 runs Limits applied: 5 posts, 1 page$0.037

Two things Facebook cannot do at any price: page followers are not enumerable (verified across three candidate actors — none returns the people), and a Page has no public following list. Both are platform limits.

Flow diagrams

current declared primary barely used

One account refresh. The tier order on paper is the reverse of the tier order in practice.

1
Step: first choice for posts (barely used)
What this isgd_lkaxegm826bjpoo9m5Bright Data dataset
“Facebook — Pages Posts by Profile URL” — not an Apify program but a Bright Data dataset, called by its ID against one web address. There is no public page for it. Give it a page link, it returns that page’s posts.
Declared primary. Too slow to lead, so it serves almost nothing. Bundles 9 page_* fields free — all discarded, and page_followers is rounded.
$0.0015/post40.5 s7 of 310 posts
2
Step: the backup that actually does the work
What this isapify/facebook-posts-scraperApify actor
“Facebook Posts Scraper” — a rented program that reads a Facebook page’s posts. Eight times faster than the first choice, which is why it ends up doing nearly all the work.
No comment count in the payload, so comments_count is 61/302 on this path.
$0.004 + $0.001 start5.3 s302 of 310 posts
3
Step: fetch the page profile (separate charge)
What this isapify/facebook-pages-scraperApify actor
“Facebook Pages Scraper” — returns a page’s own details — exact follower count, category, contact info. It returns no posts, so it cannot be merged with the step above.
The only exact follower count. Returns no posts, so no bundle exists to exploit.
$0.00828.0 sregistry says $0.00246
4
Step: fetch comments
What this isapify/facebook-comments-scraperApify actor
“Facebook Comments Scraper” — give it a post’s web address and it returns the comments beneath it. The only Facebook comment source we have.
Needs post URLs from step 2
$0.002 + $0.001 start
Priced against a tier that runs 2% of the time, and billed 3.3× over the recorded page rate.
FixWhyCost
Make Apify the declared primary for postsIt already serves 302 of 310. Bright Data's 40.5 s is too slow to lead, and pretending otherwise prices every estimate against a tier that rarely runsnone
Map video_view_count and count_reactions_typeBoth arrive on every Bright Data row and neither is read — views and reactions are 0/7 on that pathnone
Map is_verified from the pages actor0 of 11 accounts have it, though it is returnednone
Correct the pages rate to $0.0082Registry records $0.00246, and the job runs monthly so the error compounds quietlynone

Current flow

Five jobs, and TikTok is already on the cheapest wiring in the project.

apidojo/tiktok-scraper does two jobs at once: it takes a profile URL or a video URL in the same startUrls field, and it returns the full channel object with every post — so the profile costs nothing extra. At $0.0003 a post it is the cheapest post source of any platform here.

Bright Data's gd_l1villgoiiidt09ci sits behind it as a fallback. It works, but it returns top posts ranked by engagement rather than a chronological history, so it can miss a brand-new post.

Comments come from apidojo/tiktok-comments-scraper and need post URLs. Followers come from clockworks/tiktok-followers-scraper and need only the handle. Ads come from data_xplorer/tiktok-ads-library-fast, searched by advertiser name rather than id.

Misconceptions

TikTok already does the thing Instagram should be doing
Who said it
The assumption that every platform needs a separate call to refresh account details like follower count.
What I found
TikTok does not. The account details — name, username, bio, follower count, verified tick — come attached to every single post. So asking for just one post is enough to refresh an account's stats. This is exactly the free bundle Instagram was throwing away, and here it is already being used properly.
Action: refresh account stats · Actor: apidojo/tiktok-scraper · $0 extra — rides along with posts
We pay for the song on every video and then bin it
Who said it
Nobody decided this — there is simply no column for it.
What I found
Every post arrives with the song's title, artist, album, length and cover picture. We save none of it. On TikTok the sound is how a video spreads — videos go viral because of the audio they use — so right now you cannot answer "which sound did this video use?" for any video we hold. We have already paid for that answer 63 times.
Action: save the song details · Actor: apidojo/tiktok-scraper · $0 — already paid for · on 100% of posts
There is a charge just for starting a job, and our price list has nowhere to put it
Who said it
The registry lists clockworks/tiktok-followers-scraper at $0.00102 per person and no charge for starting.
What I found
Apify's live price list says $0.001 per person plus $0.001 every time the job runs. On the 25-person minimum that makes the real bill about 4% higher than quoted. More importantly, our registry file has no field at all for a start-up charge — and twelve of our actors charge one. The worst is the TikTok ads actor at $0.025 just to start. None of those fees has ever reached an estimate.
Action: get followers · Actor: clockworks/tiktok-followers-scraper · quoted $0.00102 → real $0.001 + $0.001/run ~4% under
Two columns will never fill, no matter which actor we buy
Who said it
The database has reposts_count and quotes_count columns for TikTok, which implies someone expected them to fill.
What I found
Both are empty for all 63 TikTok posts, and they always will be — TikTok does not publish either number. This is not a vendor problem and no actor can fix it. The share count we do store arrives free with the posts.
Action: fill reposts / quotes · Actor: none exists · impossible at any price
Three actors promise resharers and all three answer a different question
Who said it
Three actors on Apify are all called "TikTok Repost Scraper", which sounds exactly like what we want.
What I found
They answer it backwards. We want "who reshared this post". All three take an account link and tell you what that account has reshared. That is the opposite direction, and it is something we already get free inside the post data. Buying any of them would be money spent on the wrong answer.
Action: find who reshared a post · Actor: all 3 candidates · rejected — wrong direction
US TikTok ads cannot be collected, whatever the settings claim
Who said it
The ads actor's own settings list US as a region you can pick.
What I found
Pick it and the actor refuses the job when it runs. The list of options and what the actor actually accepts do not match. The real coverage is Europe and the UK only, because this ad library exists to satisfy a European transparency law — it was never meant to be a worldwide archive.
Action: collect US ads · Actor: data_xplorer/tiktok-ads-library-fast · impossible · plus $0.025 to start any run

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
apidojo/tiktok-scraper "TikTok Scraper"live — account posts and one video by URL, same actor
InputstartUrls — an account link or a single video link, same field either way — plus a count.
ReturnsPost details — views, likes, comments, shares, bookmarks, video, hashtags, the song (title, artist, album, cover) — and the whole account profile attached to every post.
idtitleviewslikescommentssharesbookmarksvideouploadedAtuploadedAtFormattedhashtagssongchannelpoicollabInfosubtitleInformationpostPageimagesinputSource song — title, artist, album, duration, cover art, on every post, no column · hashtags — the tags and entity_tags tables are both 0 rows · poi (place), collabInfo, subtitleInformation, postPage — no columns · parts of channel beyond follower count reposts_count and quotes_count — 0/63. TikTok publishes neither. thread_id, post_owner_handle, posting_tool also 0/63 $0.0003/post
6.0 s
gd_l1villgoiiidt09ciBright Data — "TikTok — Profiles" fallback, rarely runs
no public page
Inputan account's profile web address.
ReturnsProfile details plus top posts — up to 17 best-performing and pinned videos with view counts and descriptions. Ranked by engagement, not newest-first.
top_videos (17)top_posts_datapinned_posts, each with video_urlplaycountdescriptionhashtags, plus profile metadata — (fallback only) Chronological order. It returns top posts by engagement, so a brand-new post can be missed entirely $0.0015/profile
apidojo/tiktok-comments-scraper "TikTok Comments Scraper"live — comments
Inputvideo web addresses.
ReturnsComment details — text, date, likes, reply count, language, whether the creator liked it, and the commenter.
idtextcreatedAtlikeCountreplyCountcommentLanguageuserisAuthorLiked commentLanguageisAuthorLiked — no columns —$0.0003/comment
13.3× cheaper than the actor it replaced
clockworks/tiktok-followers-scraper "TikTok Followers Scraper"live — followers
Inputan account handle.
ReturnsA follower list — username, nickname, bio, avatar, follower / following / post counts, verified flag and account age. Richer than the Instagram equivalent.
username, nickname, bio, avatar, follower / following / post counts, verified flag, account age — mapped more completely than Instagram's equivalent — $0.001/person
+ $0.001 start
registry has $0.00102, no start fee
data_xplorer/tiktok-ads-library-fast "TikTok Ads Library Fast"live — ad library
Inputan advertiser name (not an ID) and a region.
ReturnsAd details — creatives, advertiser and region. Europe and the UK only — a US region is rejected when the job runs.
ad creatives, advertiser, region— US ads. Coverage is EU/EEA + UK only — the schema advertises a US region and the runtime validator rejects it. Searches by advertiser name, not id $0.0015/ad
+ $0.025 start
clockworks/tiktok-comments-scraper "TikTok Comments Scraper"disabled revert copy — DISABLED_tiktok_clockworks
Inputvideo web addresses.
ReturnsComment details, but with a thinner commenter object than the live actor returns.
comments, without the fuller user object— (never runs)—$0.001/comment
TOTAL — measured test spend1 run Limit applied: 10 posts$0.003

Not obtainable at any price: per-post resharer lists. All three "TikTok Repost Scraper" actors take profile links and answer a different question.

Flow diagrams

current already on the cheapest wiring

One account refresh. Nothing here is mis-routed.

1
Step: fetch posts (account details come free)
What this isapidojo/tiktok-scraperApify actor
“TikTok Scraper” — a rented program that takes either an account link or a single video link in the same box. Every post it returns carries the whole account profile attached, so account stats cost nothing extra.
startUrls takes a profile URL or a video URL. The channel object rides along on every post, so no separate profile call exists.
$0.0003/post6.0 s10 posts tested
2
Step: fetch comments
What this isapidojo/tiktok-comments-scraperApify actor
“TikTok Comments Scraper” — give it a video’s web address, it returns the comments underneath. 13 times cheaper than the program it replaced.
Needs post URLs from step 1
$0.0003/comment
3
Step: fetch the follower list
What this isclockworks/tiktok-followers-scraperApify actor
“TikTok Followers Scraper” — give it a username, it lists the people following that account — with their bios, which the Instagram equivalent does not provide.
Handle only. Carries a $0.001 start fee the registry does not record.
$0.001 + $0.001 startmin 25
4
Step: fetch ads from TikTok’s ad library
What this isdata_xplorer/tiktok-ads-library-fastApify actor
“TikTok Ads Library Fast” — searches TikTok’s public ad archive by advertiser name (not ID). The archive exists to satisfy a European transparency law, so it only covers Europe and the UK.
By advertiser name. EU/EEA + UK only — US is rejected at runtime.
$0.0015 + $0.025 startEU/UK only
Cheapest post source in the project. The only errors are a missing start fee and a field that is bought and discarded.

Current flow

Five jobs across four actors, and the best-mapped platform in the project — likes, comments_count, shares, reposts_count, quotes_count, bookmarks_count, thread_id and posting_tool are all 398/398.

Posts run through apidojo/tweet-scraper. The tier resolver is called, but pull-data-x.js line 45 hardcodes the run URL, so the resolver's answer is discarded — see the misconceptions below.

Replies are the one place xquik/x-tweet-scraper is used, in conversationIds mode, and it reuses posts.thread_id so it needs the posts job first. One tweet by id goes to kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest, followers to kaitoeasyapi/premium-x-follower-scraper-following-data, and retweeters to api-ninja/x-twitter-replies-retweets-scraper.

Bright Data cannot serve X at all: its gd_lwxkxvnf1cynvib9co dataset needs a specific tweet URL and cannot enumerate a profile.

Misconceptions

The code ignores our own choice and uses the dearer actor
Who said it
The registry picks xquik/x-tweet-scraper as the actor to use for X posts, and the code does ask the chooser which actor to use.
What I found
The answer is thrown away on the very next line. pull-data-x.js line 45 has the dearer actor's web address typed directly into it, so that is what runs — every time, no matter what the chooser says. I ran both actors against the same account with ten tweets each and compared the real bills:
Action: get posts · Actor: apidojo/tweet-scraper → xquik/x-tweet-scraper · $0.0004 → $0.00015 2.67× less · 4.7 s → 2.5 s · fix is deleting one line
Cost for 10 tweetsPer tweetLatency
apidojo/tweet-scraper — running today$0.0040$0.000404.7 s
xquik/x-tweet-scraper — registry primary$0.0016$0.000152.5 s
Switching actors loses one field, and nothing reads it
Who said it
The worry that moving to the cheaper actor would cost us data.
What I found
I compared the two answers field by field. They fill every X column the same way except two. One is just a renaming — isQuote becomes isQuoteStatus, a two-line change. The other is real: the cheaper actor does not send source, which is the app the tweet was posted from ("Twitter for iPhone"). That column is filled on all 398 posts — but no screen, chart or filter in the dashboard reads it. If it stays unused, the switch costs nothing at all.
Action: switch posts actor · Loses: posting_tool (398/398 filled, 0 readers) · keep apidojo as backup if it ever matters
Asking for one tweet bills us for fifteen
Who said it
The actor is literally named "...Pay Per Result Cheapest" and charges $0.00022 per result, which looks like the cheapest way to refresh a single tweet.
What I found
I asked it for one tweet. It sent back 15 rows — the real tweet plus 14 empty filler rows with the ID -1 — and charged for all fifteen. It ignores the setting that is supposed to limit how many results come back. So the true price of one tweet is about $0.0033, roughly 15× the advertised rate.
Action: refresh one tweet · Actor: kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest · advertised $0.00022 → real ≈$0.0033 15× more
Having four backups does not mean we are protected
Who said it
Four extra X actors are registered as backups, which suggests that if the main one breaks, something else takes over.
What I found
None of the four can ever run. The resharer code only ever looks at the first choice in the list, so the three behind it are never reached. And the comments code is built with one fixed actor per platform, so the fourth cannot be reached either. They are listed, but they are decoration.
Action: fall back when the main actor fails · Actors: 4 registered · all unreachable — no real protection
The retweeter actor quietly returns the wrong people
Who said it
The actor is called "Replies & Retweets Scraper", so asking it for retweeters sounds straightforward.
What I found
If you do not explicitly tell it retweets, it defaults to replies — and hands back people who replied instead of people who retweeted. It does not fail or warn; it just answers a different question. It also charges $0.01 just to start, which our registry has no way to record.
Action: get retweeters · Actor: api-ninja/x-twitter-replies-retweets-scraper · $0.00035 + $0.01 start · must set category: 'retweets'
Our biggest single bill buys data that one panel reads
Who said it
Nobody flagged it — it only shows up when you add the ledger up.
What I found
The X follower job is $3.77 of $9.55 total spending — the largest line by far. It is driven by a 200-person minimum: you cannot ask for fewer. All 25,219 follower rows we hold are read by exactly one thing — the results panel in the Capability Explorer.
Action: get followers · Actor: kaitoeasyapi/premium-x-follower-scraper-following-data · $3.77 of $9.55 spent · minimum 200 per run

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
apidojo/tweet-scraper "Tweet Scraper"live — hardcoded in pull-data-x.js line 45, overriding the registry
Inputan account handle or search term, plus a tweet limit.
ReturnsTweet details — text, date, likes, replies, retweets, quotes, bookmarks, views, media, and source (the app it was posted from).
fullTexttextcreatedAtlikeCountreplyCountretweetCountquoteCountbookmarkCountviewCountconversationIdisRetweetisQuoteisPinnedisConversationControlledsourcemediaextendedEntitiesentitiescardplacelangpossiblySensitiveauthortwitterUrlretweetvideos cardplacelangpossiblySensitiveisConversationControlledextendedEntitiesentitiesauthor — no columns — $0.0004/tweet
4.7 s
xquik/x-tweet-scraper "X Tweet Scraper"live — replies only the registry names it primary for posts too
Inputan account handle for posts, or conversationIds to fetch the replies under a thread.
ReturnsTweet details — all the same counts, plus reply-chain fields. Missing only source, the posting app.
same counts, plus inReplyToIdinReplyToUserIdinReplyToUsernameisQuoteStatusisNoteTweetisTranslatabledisplayTextRangeeditviewStatepossiblySensitive isNoteTweetisTranslatabledisplayTextRangeeditviewState source — the posting tool. The one field apidojo has and this does not, and posting_tool is filled 398/398 today $0.00015/tweet
2.5 s
kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest "Twitter (X) Data Tweet Scraper Pay Per Result Cheapest"live — one tweet by id
Inputa single tweet's ID.
ReturnsOne tweet with live counts — but padded to 15 rows, 14 of them empty with the ID -1, and billed for all 15.
the full tweet with live counts— A clean single result — it returns 15 rows for one tweet (14 filler rows with id -1) and bills for all 15 $0.00022 × 15 min
≈ $0.0033/post
kaitoeasyapi/premium-x-follower-scraper-following-data "Premium X Follower Scraper — Following Data"live — followers and following
Inputan account handle and a direction — followers or following.
ReturnsA list of people — username, name, bio, follower count, verified flag, post count and account age.
username, name, bio, followers_count, verified flag, post count, account age — richer than the Instagram follower actor— $0.00015/person
min 200
$3.77 of $9.55 total ledger spend
api-ninja/x-twitter-replies-retweets-scraper "X (Twitter) Replies & Retweets Scraper"live — retweeters, Explorer panel only
Inputa tweet's web address and category, which must be set to retweets.
ReturnsA list of people — screen name, name, follower count. Users only, never tweets.
flat user objects: screen_namenamefollowers_count — Reply tweets — it returns users, never tweets. category defaults to REPLIES and must be set to retweets or it answers the wrong question $0.00035/item
+ $0.01 start
apidojo/twitter-replies-scraper unreachable
Inputa tweet's web address.
ReturnsReply tweets. Never runs — the comment layer uses one fixed actor per platform.
replies——$0.0004 + $0.014/query
seemuapps/x-tweet-retweeters-scraper unreachable (tier 2)
Inputa tweet's web address.
ReturnsA list of people who retweeted. Never runs — the code reads only the first choice.
retweeters——$0.0015 + $0.00005
khadinakbar/x-tweet-engagement-scraper unreachable (tier 3)
Inputa tweet's web address.
ReturnsReplies, quotes and retweets in one call — the only actor offering all three together. Never runs.
replies, quotes and retweets in one call——$0.006
seemuapps/x-quote-tweets-scraper CLI only, never run
Inputa tweet's web address, typed by hand at a terminal.
ReturnsQuote tweets. No scheduled job or dashboard button triggers it.
quote tweets——$0.003
data_direct/twitter-tweet-quotes-scraper unreachable (tier 2)
Inputa tweet's web address.
ReturnsQuote tweets. Registered as a second choice that is never reached.
quote tweets——$0.006
gd_lwxkxvnf1cynvib9coBright Data — "X — Posts by URL" never wired
Inputone tweet's exact web address. It cannot take an account handle.
ReturnsOne tweet, enriched. Because it cannot list an account's tweets, Bright Data serves no X capability at all.
one tweet, enriched— Cannot enumerate a profile — it needs a specific status URL, which is why Bright Data serves no X capability—
TOTAL — measured test spend2 runs, same account Limit applied: 10 tweets each$0.0056

Flow diagrams

current the resolver is consulted, then ignored

One account refresh. Two vendors doing one vendor's job.

1
Step: fetch posts (the dearer program, forced)
What this isapidojo/tweet-scraperApify actor
“Tweet Scraper” — a rented program that reads an account’s tweets. Its web address is typed directly into our code, so it runs no matter what the price list chooses.
Every X post pull billed at 2.5× the registry rate. Only advantage: source.
$0.0004/tweet4.7 s10 tweets tested
2
Step: fetch replies (the cheap program, used for less)
What this isxquik/x-tweet-scraperApify actor
“X Tweet Scraper” — the same kind of program, 2.67× cheaper and twice as fast. Today it is only trusted with replies, even though the price list names it first choice for posts as well.
conversationIds mode, reuses posts.thread_id, so it needs step 1 first.
$0.00015/reply2.5 s
3
Step: refresh a single tweet
What this iskaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapestApify actor
“Twitter (X) Data Tweet Scraper Pay Per Result Cheapest” — advertised as the cheapest per result. Ask it for one tweet and it returns 15 rows — 14 of them empty padding — and charges for all 15.
Ignores maxItems: 15 rows billed for 1 tweet.
≈$0.0033/post15-row floor
4
Step: fetch the follower list
What this iskaitoeasyapi/premium-x-follower-scraper-following-dataApify actor
“Premium X Follower Scraper — Following Data” — lists who follows an account, with bios and follower counts. You cannot ask for fewer than 200 people, which is what makes it our biggest single bill.
The biggest line in the whole ledger, and the data is read by one panel.
$3.77 of $9.55min 200 rows
Two vendors, the cheaper one relegated to replies, and the registry describing a routing that does not happen.

posting_tool records "Twitter Web App" or "Twitter for iPhone". It is complete data, but no tab, chart or filter reads it. If it stays unused, the switch costs nothing at all.

Current flow

YouTube is the only one of the seven networks with a genuinely free enumeration route, and it is wired free-first.

A pull starts by asking fetchFree(). That resolves the channel id once (cached on the account), reads the public RSS feed at feeds/videos.xml?channel_id=…, then enriches each video through the official YouTube Data API v3 to fill the like and comment counts RSS omits. No key for RSS; the Data API needs YOUTUBE_API_KEY and gives 10,000 units a day free.

fetchFree() returns null the moment limit > 15 — the RSS feed carries only 15 entries. FIRST_PULL_LIMIT is 30, so every initial backfill falls straight through to streamers/youtube-channel-scraper. Incrementals ask for 8 and correctly stay free.

Comments are a separate paid call to streamers/youtube-comments-scraper. Bright Data cannot serve YouTube at all — gd_lk56epmy2i5g7lzu0k needs a specific video URL and cannot enumerate a channel.

Misconceptions

"The paid actor is the better source." It is not. Same channel, 12 videos, measured:
CostLatencyViewsLikesDuration
Free RSS + Data API$00.7 s12/1212/1210/12
streamers/youtube-channel-scraper$0.01211.0 s12/120/1212/12

15× faster, free, and the only route that returns like counts. The paid actor wins on exactly two things: more than 15 videos, and the channel stats block.

The free route is not failing — one line of code skips past it
Who said it
The paid actor brought in 197 of our 207 YouTube posts, which looks like proof that the free route does not work well enough.
What I found
The free route is never given the chance. YouTube's free feed holds 15 videos, and the code says if (limit > 15) return null; — meaning "if you want more than 15, give up on free entirely". The first time we pull an account we ask for 30. So every first pull jumps straight to paying, for all 30, instead of taking 15 free and buying only the rest.
Action: first pull of a channel · Actor: free RSS → streamers/youtube-channel-scraper · $0 → $0.001/video · 0.7 s vs 11.0 s
Like counts are missing on 166 videos because of the same line
Who said it
likes is empty on most YouTube posts, which looks like the data is simply not available.
What I found
It is available and it is free. Google's own free API fills like counts — on the free route it filled 12 out of 12. The paid actor fills 0 out of 12. But the free top-up step only runs on the free route, so every paid row is left with no likes. likes is filled on 41 of 207 posts, which lines up exactly with how rarely the free route is used.
Action: fill like counts · Source: YouTube Data API v3 · $0 — free quota, 10,000/day · fixes 41/207 → nearly all
Comment prices are quoted at nearly three times the real cost
Who said it
The registry says streamers/youtube-comments-scraper costs $0.004 per comment.
What I found
It costs $0.0015. This one is harmless to the budget — we over-reserve rather than under-reserve — but it makes YouTube comment collection look 2.7× more expensive than it is, which may be putting people off using it.
Action: get comments · Actor: streamers/youtube-comments-scraper · quoted $0.004 → real $0.0015 2.7× over
Subscriber lists cannot be bought from anyone
Who said it
Several actors on Apify advertise "YouTube subscribers", which suggests the list of people is for sale.
What I found
Every one of them gives back a number, not the people. YouTube keeps subscriber lists private on purpose — it is a platform rule, not a gap in the market. The same is true of the channels an account subscribes to. No amount of money changes this.
Action: list subscribers · Actor: none exists · impossible at any price

Actors and data sets

Name, source and statusReturns Returned but not usedWanted, but no source returns itCost
YouTube channel RSSyoutube.com/feeds/videos.xml?channel_id=… live — tried first, free
Inputa channel ID, appended to a public feed address. No key, no account.
ReturnsThe 15 newest videos — id, link, title, publish date, view count, thumbnail. No likes, no comment counts, and never more than 15.
videoIdurltitlepublishedviewsthumbnailUrl — More than 15 videos. A hard feed ceiling, which is why fetchFree() bails above 15 and first pulls go paid $0 · 0.7 s
YouTube Data API v3 googleapis.com/youtube/v3live — enriches the row above
Inputthe video IDs taken from the feed above, plus a free API key.
ReturnsThe numbers the feed leaves out — like count, comment count and duration. An add-on to the row above, not a separate source.
likeCountcommentCountduration — Nothing extra — it is an enrichment of the RSS row, not a separate route $0, 10k units/day
needs YOUTUBE_API_KEY
streamers/youtube-channel-scraper "Fast YouTube Channel Scraper"live — 197 of 207 stored posts
Inputa channel's web address and how many videos to fetch.
ReturnsVideo details plus channel statistics — views, duration, title, date, and the channel's subscriber count, total views, join date and description. No like counts.
viewCountdurationtitledateurlvideoIdnumberOfSubscriberschannelTotalViewschannelTotalVideosisChannelVerifiedchannelJoinedDatechannelLocationchannelDescriptionchannelDescriptionLinksaboutChannelInfochannelAvatarUrlchannelBannerUrlisAgeRestricted channelBannerUrlchannelDescriptionLinksisAgeRestrictedchannelLocation — no columns · the channel block is otherwise the reason to keep this actor Like counts. Returned likes on 0 of 12 videos in a live run. likes is 41/207 overall $0.001/video
11.0 s
streamers/youtube-comments-scraper "YouTube Comments Scraper"live — comments
Inputa video's web address and a sort order — top comments or newest first.
ReturnsComment details — id, text, author, date, likes and replies.
comment id, text, author, date, likes, replies; sortCommentsBy TOP_COMMENTS or NEWEST_FIRST (verified working) —— $0.0015/comment
registry says $0.004
gd_lk56epmy2i5g7lzu0kBright Data — "YouTube — Videos" never wired
Inputone video's exact web address. It cannot take a channel.
ReturnsOne video, enriched. Because it cannot list a channel's videos, Bright Data serves no YouTube capability.
one video, enriched— Cannot enumerate a channel — it needs a specific video URL, which is why Bright Data serves no YouTube capability —
TOTAL — measured test spend2 runs (1 free, 1 paid) Limit applied: 12 videos each$0.012

Not obtainable at any price: subscriber lists and a channel's subscriptions. Both are private by platform design — every candidate actor returns a count, not the people.

Flow diagrams

current free below 15 videos, paid above

The branch that decides everything is a single if.

1
Step: work out the channel’s ID, once
What this isYouTube channel RSS feedfree, no vendor
“YouTube public feed” — not a rented program at all — a public feed YouTube publishes for every channel. No key, no bill, no account.
One lookup per account, then never again.
$0
2
if (limit > 15) return null;
The RSS feed carries 15 entries, so the free path refuses anything larger rather than paging.
FIRST_PULL_LIMIT = 30INCREMENTAL = 8
3a
Step: routine refresh — the free path
What this isYouTube Data API v3free, 10k/day
“Google’s official API” — Google’s own official service, used to add the like and comment counts the public feed leaves out. Free up to 10,000 requests a day.
Likes filled 12/12. This is the good path, and it runs on refreshes only.
$00.7 slikes 12/12
3b
Step: first-ever pull — goes paid
What this isstreamers/youtube-channel-scraperApify actor
“Fast YouTube Channel Scraper” — a rented program that reads a channel’s full back-catalogue. It is the only way past the 15-video limit — but it returns no like counts at all.
No Data API enrichment on this path, and the actor returns no likes — so these rows have none.
$0.001/video11.0 slikes 0/12
4
Step: fetch comments
What this isstreamers/youtube-comments-scraperApify actor
“YouTube Comments Scraper” — give it a video link, it returns the comments, newest-first or top-first. Really costs $0.0015 each, not the $0.004 on file.
Separate paid call, billed at 2.7× the rate the registry records.
$0.0015/commentregistry says $0.004
197 of 207 stored posts came from the paid actor — not because the free path fails, but because a limit skips it. likes is 41/207 as a direct result.

Current flow

Nine jobs across two vendors, and the most expensive platform per unit — LinkedIn is the hardest network to scrape, which is why competition is thin and prices are higher.

Company posts come from harvestapi/linkedin-company-posts, which has a floor of 8: asking for 2 returned 8 and billed for 8.

Both profile jobs lead with Bright Data, and that position is earned on price rather than assumed — gd_l1vikfnt1wgvvqz95w for a company and gd_l1viktl72bvl7bjuj0 for a person, both at $0.0015 against Apify's $0.004. The harvestapi actors sit behind them as fallbacks.

Comments come from harvestapi/linkedin-post-comments and need post URLs, so the chain runs three deep: posts → comments → commenter profile. One post by URL goes to apimaestro/linkedin-post-detail, resharers to datadoping/linkedin-post-repost-scraper, and ads to data_xplorer/linkedin-ad-library-scraper.

Bright Data's LinkedIn Posts dataset gd_lyy3tktm25m4avu764 is never wired — it needs a specific post URL and cannot discover an account's posts.

Misconceptions

"The post bundle switches are tested and ignored." That was true and no longer is. The registry records scrapeComments / scrapeReactions as having run and returned nothing. Apify now prices comment and reaction events on that actor, so both were re-run with maxComments: 5 and maxReactions: 5 against a 10-post ask:
ItemsChargedCost
Posts only (10)10post: 10$0.0201
Posts + bundles on59post: 10, reaction: 47, comment: 2$0.1181

5.9× the cost. Reactions bill at $0.002 each — the same as a post — and 47 arrived for a 10-post ask. Worse, the extras come back as separate flat rows, not nested arrays: the first item's keys are type, id, reactionType, actor, postId, query, a reaction record rather than a post. The existing parser would need rewriting. And it yielded 2 comments across 10 posts, so it is a poor comment source too. Leave both switches off — but rewrite the note, because "ignored" is wrong.

Action: turn on comment + reaction bundles · Actor: harvestapi/linkedin-company-posts · $0.0201 → $0.1181 5.9× more · 10 posts asked → 59 rows billed
Comment prices are quoted at double the real cost
Who said it
The registry says harvestapi/linkedin-post-comments costs $0.004 per comment.
What I found
It costs $0.002 — exactly half. Over-quoting is the safer direction, but it makes LinkedIn comments look twice as expensive as they are.
Action: get comments · Actor: harvestapi/linkedin-post-comments · quoted $0.004 → real $0.002 2× over
The ad library costs double what we reserve for it — the dangerous direction
Who said it
The registry says data_xplorer/linkedin-ad-library-scraper costs $0.0005 per ad.
What I found
It costs $0.001 — twice as much. This is the direction that actually causes harm: the spending guard sets aside half the money it should, so a job can go over a limit it believed it was safely inside. Only two of our seven wrong prices lean this way, and this is one of them.
Action: collect ads · Actor: data_xplorer/linkedin-ad-library-scraper · quoted $0.0005 → real $0.001 2× under-quoted
We get charged when a job finds nothing
Who said it
Nothing in the registry — it can only record a price per item.
What I found
harvestapi/linkedin-company-posts has a charge called no-result at $0.001 — you pay it when the run comes back empty. It also charges a small fee just to start. Our registry can record neither, so a run that finds nothing currently looks free in every estimate.
Action: check an account with no new posts · Actor: harvestapi/linkedin-company-posts · $0.001 for nothing never quoted
LinkedIn has no Instagram-style saving hiding in it
Who said it
My own hope, after the Instagram result — maybe LinkedIn also sends posts and profile together and we could delete a call.
What I found
It does not. No vendor sends posts bundled with the company profile. The one bundle that does exist costs 5.9× more. And Bright Data already leads both profile jobs at $0.0015 against Apify's $0.004, so the cheap choice is already being made. The wiring here is correct — only the written-down prices are wrong.
Action: merge calls like Instagram · Actor: all LinkedIn vendors · no saving exists
Two minimums are real and should be left alone
Who said it
They look like odd hard-coded numbers in our code.
What I found
Both are the vendors' own rules. The posts actor never returns fewer than about 8 — I asked for 2 and got 8, and was billed for 8. The resharer actor refuses any request under 10 with an outright error (Field input.max_reposts must be >= 10). Someone already found these and wrote them into the code. They are worth keeping.
Action: ask for fewer items · Actors: company-posts (floor 8), repost-scraper (floor 10) · cannot go lower

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
harvestapi/linkedin-company-posts "LinkedIn Company Posts Scraper"live — company posts
Inputa company page's web address and a post limit. Optional switches can also pull comments and reactions.
ReturnsPost details — content, date, engagement counts, author, media, images, video, article, repost info. Never fewer than about 8 posts.
contentpostedAtengagementsocialContentstatsauthormediapostImagespostVideoarticlerepostrepostIdreshared_postis_resharedshareUrnshareLinkedinUrllinkedinUrlentityIdplatformPostIdcommentIdsreactionIdsnewsletterTitlenewsletterUrlcontentAttributes articlenewsletterTitlenewsletterUrlcontentAttributesshareUrnentityIdcommentIdsreactionIds — no columns View counts. views is 0/93 — LinkedIn publishes impressions only to the post owner $0.002/post + $0.00005 start
floor of 8
bundles: reaction $0.002, comment $0.002
gd_l1vikfnt1wgvvqz95wBright Data — "LinkedIn — Company Profile" live, primary — cheaper than Apify
no public page
Inputa company page's web address.
ReturnsCompany profile details — follower count, employee count, about text, specialities, industries, headquarters and founding year.
followers, employees, about, specialties, industries, headquarters, founded year ——$0.0015/profile
harvestapi/linkedin-company "LinkedIn Company Scraper"fallback for the row above
Inputa company page's web address.
ReturnsCompany profile details — the same shape as the Bright Data row above, at 2.7× the price. Backup only.
same shape— (fallback only)—$0.004 + $0.00005 start
gd_l1viktl72bvl7bjuj0Bright Data — "LinkedIn — Person Profile" live, primary
no public page
Inputan individual's profile web address.
ReturnsPerson profile details — name, city, current position, about text, current company, work history and education.
name, city, position, about, current_company, experience, education ——$0.0015/person
harvestapi/linkedin-profile-scraper "LinkedIn Profile Scraper"fallback for the row above
Inputan individual's profile web address, optionally asking for an email too.
ReturnsPerson profile details, same shape as above, plus an email address if requested — which costs 2.5× more.
same, plus optional email— (fallback only)— $0.004
$0.01 with email
harvestapi/linkedin-post-comments "LinkedIn Post Comments Scraper"live — comments
Inputa post's web address.
ReturnsComment details — id, text, author, date, likes and the commenter's job title, which no other network gives us.
comment id, text, author, job title, date, likes — the job title is something no other network returns main-profile and full-profile enrichment events— $0.002/comment
registry says $0.004
apimaestro/linkedin-post-detail "LinkedIn Post Detail"live — one post by URL
Inputone post's web address.
ReturnsOne post in full — reactions broken down by type, comments, shares and video.
reactions with a per-type breakdown, comments, shares, video the per-type reaction split—$0.005 flat
datadoping/linkedin-post-repost-scraper "LinkedIn Post Repost Scraper"live — resharers, Explorer panel only
Inputa post's web address and a count that must be 10 or more — fewer is refused outright.
ReturnsA list of people who reshared it — names, profile links and any commentary they added.
named resharers with profile URLs and any commentary they added —— $0.0014
hard floor of 10 — fewer is an HTTP 400
data_xplorer/linkedin-ad-library-scraper "LinkedIn Ad Library Scraper"live — ads (337 rows)
Inputan advertiser to look up in LinkedIn's public ad library.
ReturnsAd details — creatives and advertiser. 337 rows collected so far.
ad creatives, advertiser—— $0.001/ad
registry says $0.0005 — under-quoted
apimaestro/linkedin-post-reshares unreachable (tier 2)
Inputa post's web address.
ReturnsA list of people who reshared it — same shape as the live actor. Second in a list only ever read to the first.
same reposter shape——$0.005
benjarapi/linkedin-company-posts unreachable — the primary's URL is hardcoded
Inputa company page's web address.
ReturnsCompany post details. Never runs — the first choice's address is hardcoded.
company posts——$0.002
gd_lyy3tktm25m4avu764Bright Data — "LinkedIn — Posts" never wired
Inputone post's exact web address, matching /(pulse|posts|feed/update)/.
ReturnsOne post, enriched. It cannot list an account's posts, so it is never wired in.
one post, enriched— Cannot enumerate an account — it needs a post URL matching /(pulse|posts|feed\/update)/—
TOTAL — measured test spend1 run, bundles on Limits applied: 10 posts, 5 comments, 5 reactions → 59 rows billed$0.118

Not offered: LinkedIn followers and following. A company-followers actor exists but has about 315 users and has never been run, so its rate is unknown and it is not wired.

Flow diagrams

current 5 calls, two vendors, three deep

One company refresh. The wiring is sound; the recorded prices are not.

1
Step: fetch a company’s posts
What this isharvestapi/linkedin-company-postsApify actor
“LinkedIn Company Posts Scraper” — give it a company page, it returns that company’s posts. It never returns fewer than about 8 — ask for 2 and you get, and pay for, 8.
Bundle switches off. Asking for 2 still returns and bills 8.
$0.002/post + $0.00005floor of 8
2
Step: fetch the company’s own details
What this isgd_l1vikfnt1wgvvqz95wBright Data dataset
“LinkedIn — Company Profile” — a Bright Data dataset called by ID, with no public page. Returns followers, employee count, industry and headquarters. Cheaper than the Apify equivalent, which is why it leads.
Primary on price. harvestapi at $0.004 sits behind it.
$0.00152.7× cheaper than fallback
3
Step: fetch comments on those posts
What this isharvestapi/linkedin-post-commentsApify actor
“LinkedIn Post Comments Scraper” — returns the comments under a post — including each commenter’s job title, which no other network gives us.
Needs post URLs from step 1. Billed at half the registry's rate.
$0.002/commentregistry says $0.004
4
Step: look up each commenter
What this isgd_l1viktl72bvl7bjuj0Bright Data dataset
“LinkedIn — Person Profile” — a Bright Data dataset for an individual person — job, employer, history. Third link in the chain, so it cannot run until comments exist.
Third link in the chain: posts → comments → profile.
$0.0015/person3 deep
5
Step: resharers and ad library
What this isdatadoping/linkedin-post-repost-scraperApify actor
“LinkedIn Post Repost Scraper” — lists who reshared a post. It refuses any request for fewer than 10. Ads come from a separate program, data_xplorer/linkedin-ad-library-scraper.
datadoping rejects fewer than 10. The ad library is billed at 2× its recorded rate.
floor of 10ads $0.001, registry $0.0005
Correct routing, two mis-recorded rates, and one under-quote the budget guard cannot see.

Current flow

One call, one actor, no fallback. Threads is the project's only documented single point of failure — and its payload is the richest of any platform, about 80 keys.

futurizerush/meta-threads-scraper is asked {"usernames":["nasa"], "max_posts": 10} and returns posts and the entire profile attached to every post: followers_count, bio, is_verified, display_name, profile_pic_url, user_id, plus emails, phones, bio_links and external_links. All present on 10 of 10 posts.

max_posts has a hard minimum of 10, so every Threads pull costs $0.045 whether one new post exists or ten.

Everything else on Threads is a dead end — comments, resharers and followers are all platform or actor limits rather than wiring gaps. Bright Data serves nothing here.

Misconceptions

A Threads run probably bills for more posts than we ask for
Who said it
The price is $0.0025 per post plus $0.005 to start, and the minimum is 10 posts — so a run should cost $0.030.
What I found
The real bill was $0.045. That is exactly what you get from 16 posts, not 10: $0.005 + 16 × $0.0025 = $0.045. It looks like the actor sends back more than you ask for and charges for all of it — the same overshoot the Facebook resharer actor has, where asking for 10 billed 12. One more run would confirm it, at a cost of about $0.03.
Action: get posts · Actor: futurizerush/meta-threads-scraper · expected $0.030 → billed $0.045 ~50% over
Never add a profile call here — it would cost a full run
Who said it
Every other platform has a separate call to refresh account details, so it looks like Threads is missing one.
What I found
The whole profile is attached to every post — follower count, bio, verified tick, picture, even email and phone fields. All present on 10 of 10 posts. Adding a separate profile call would trigger the 10-post minimum all over again to fetch information we already have in hand.
Action: refresh account details · Actor: futurizerush/meta-threads-scraper · $0 extra today · a separate call would cost a full run
We buy the account bio ten times a run and save none of it
Who said it
Nobody — there is simply no code mapping it across.
What I found
The bio came back on 10 of 10 posts — "Making the seemingly impossible, possible. ✨" — and the accounts.bio column is empty. It is exactly the same pattern as the Instagram posts we were buying twice: the data arrives, already paid for, and gets dropped on the floor.
Action: save the account bio · Actor: futurizerush/meta-threads-scraper · $0 — already paid for · arrives on 100% of posts
Every run pays for ten posts even when there is one new post
Who said it
The 10-post minimum reads like a small technical footnote.
What I found
It is the entire cost story for this platform. You cannot ask for fewer than ten, so a quiet account that posted once still bills for ten. One account is pocket change. Fifty accounts checked daily is roughly $67 a month, mostly for nothing. For accounts that post fewer than ten times a day, checking weekly collects the same posts for a fraction of the cost.
Action: daily refresh · Actor: futurizerush/meta-threads-scraper · ~$67/month at 50 accounts → weekly cadence up to 6× less
The cheap alternative is 450× cheaper and nobody uses it
Who said it
sleek_waveform/threads-scraper is dramatically cheaper, which looks like an obvious switch.
What I found
It had 18 users in 30 days — almost nobody runs it, so if it breaks nobody will notice or fix it. Threads is already the only platform here with no backup at all: if its one actor stops working, Threads collection stops dead. Swapping to an unmaintained actor to save pennies on our most fragile platform is the wrong trade. I also tested logical_scrapers/threads-post-scraper: it returned zero items and cannot list an account's posts.
Action: replace the Threads actor · Actors: 2 candidates tested · both rejected · reliability over price
Threads comments are not "not wired yet" — the option does not exist
Who said it
It sounds like a job nobody has got around to connecting.
What I found
I read the actor's full list of modes: User Posts, Reposts, Replies, Search. "Replies" means replies written by an account, not replies to a post. There is no mode that fetches the replies under a given post. It is a missing feature at the vendor, not a missing connection at our end.
Action: get comments on a post · Actor: futurizerush/meta-threads-scraper · no such mode
We know how many reshared, never who
Who said it
We store a repost count, so it seems like the names should be reachable too.
What I found
The counts arrive free on 10 of 10 posts. But the only actor that offers reposts takes an account link and returns what that account has reshared — backwards, the same trap as the Instagram and TikTok "Repost Scraper" actors. Three platforms, three times the same wrong-direction product.
Action: find who reshared a post · Actor: only candidate · rejected — wrong direction

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no actor returns itCost
futurizerush/meta-threads-scraper "Meta Threads Scraper"live — no fallback exists posts and the whole profile
Input{"usernames":["nasa"], "max_posts": 10} — an account name and a count that cannot go below 10.
ReturnsPost details plus the entire profile, attached to every post — around 80 fields. Engagement (likes, replies, reposts, quotes, views), media, 20+ true/false flags, and the account's followers, bio, verified tick, email and phone.
~80 keys.
Engagement: like_countreply_countrepost_countquote_countshare_countview_countview_count_status — all 10/10
Profile, on every post: followers_countbiois_verifieddisplay_nameprofile_pic_urlprofile_pic_hd_urluser_idusernameemailsphonesbio_linksexternal_linksprofile_urlprofile_tags
Post: text_contentpost_codepost_urlcreated_attopic_taghashtagsmentionsmentioned_accountslanguagemedia_urlmedia_urlsmedia_typemedia_width/heighthas_mediahas_audioaccessibility_captionis_ai_generatedis_editedis_gifis_paid_partnershipis_pinnedis_spoileris_sticker_postis_quote_postis_replyis_repostreply_controllocation_idlocation_namepodcast_namepodcast_urlpodcast_platformsticker_idssticker_urlsurls
plus 7 replied_to_* and 4 reposted_* fields
bio — on every post, accounts.bio is empty · emailsphonesbio_linksexternal_links — returned as arrays, empty for NASA, and nothing maps them · accessibility_captionlanguageis_ai_generatedis_editedis_spoileris_sticker_postreply_controlmedia_width/heightpodcast_*sticker_*profile_tags · the replied_to_* and reposted_* blocks Nothing extra from this actor — the gaps are the three platform limits below $0.0025/post
+ $0.005 to start
minimum 10 posts
billed $0.045 for a 10-post ask
8.9 s
logical_scrapers/threads-post-scrapertested and rejected
Inputone post's web address.
ReturnsNothing — it returned zero items on a real run, and it cannot list an account's posts at all.
zero items on a real run— Cannot enumerate an account — it scrapes one post by URL—
sleek_waveform/threads-scrapertested and rejected
Inputan account name.
ReturnsPost details, 450× cheaper — but only ~18 people used it in 30 days, so nobody maintains it.
posts— Maintenance — 18 users in 30 days. 450× cheaper and not dependable for the project's most fragile capability—
TOTAL — measured test spend1 run Limit applied: 10 posts — the hard minimum, so this is the cheapest possible Threads run $0.045

Three things Threads cannot do, all verified rather than assumed

CapabilityWhy not
CommentsThe actor has User Posts / Reposts / Replies / Search modes — none is "replies TO a given post"
Who repostedThe only candidate takes profiles and returns what an account has reposted — the opposite direction. Counts are stored free
FollowersCandidate actors exist with ~8 users in 30 days. Not offered, deliberately

Flow diagrams

current one call, three dead ends, no fallback

The whole platform is a single actor.

1
Step: fetch posts (profile comes free)
What this isfuturizerush/meta-threads-scraperApify actor
“Meta Threads Scraper” — the only program we have for Threads — there is no spare. Give it a username and every post comes back with the account’s full profile attached, around 80 fields in total.
{"usernames":["nasa"], "max_posts": 10} → posts + full profile on every post. ~80 keys, the richest payload in the project.
$0.045 a run8.9 smin 10 posts
No fallback tier exists. If this actor breaks, Threads collection stops — and both cheaper alternatives were tested and rejected.

Current flow

One actor plus a local OCR step. 427 Google ads stored.

automation-lab/google-ads-scraper is asked for ads from the Google Ads Transparency Center. Where an advertiser id is on file it uses {advertiserIds: ["AR137…"], maxAds: 10} — an exact lookup; otherwise it falls back to {searchTerms: [name]}, a fuzzy name search. There are 17 ids on file in google_advertiser_ids.

What comes back is a picture, not words. So every creative image is then read by tesseract.js running locally — no vendor, no key, no bill — using the Worker API with { blocks: true } to get line-level positions rather than a flat text blob.

The result reaches ads with ad_copy_source set to 'ocr'. Bright Data has no ad-library endpoint for any network, so all four ad capabilities in the project are legitimately single-tier.

We are not collecting ad wording that Google does publish — but we can
The gap
Google publishes real, structured wording for text ads — a headline, a body line and the display URL. Our actor asks for them and gets null every time, so today the only wording we hold comes from reading pictures. A different actor returns that wording properly on the same ads.
How big
76 of our 427 Google ads are text ads. The other 351 are images or video, where there genuinely is no wording to fetch and reading the picture stays the only option.
What fixes it
Add s-r/google-ads-transparency as a second pass for text ads only. It is not a replacement — it cannot look an advertiser up by ID, which is how our whole pipeline is keyed.
Action: collect ad wording for text ads · Actor: add s-r/google-ads-transparency alongside the current one · OCR text, 70/76 → clean title + body + display URL

Misconceptions

The ad wording is missing because of our actor, not because of Google
Who said it
Our actor lists adText, headline, body and callToAction and returns all four empty — even on an ad Google itself labels format Text. The obvious conclusion was that Google publishes ads as finished pictures and the wording simply is not there to fetch.
What I found
That conclusion was wrong. I ran two actors against the same advertiser and the same text ads. Ours returned 5 ads, all format Text, with 0 of 5 carrying any wording. s-r/google-ads-transparency returned the wording properly:
title → "Entire House / Apartment in Switzerland, Europe — from $31 | trivago"
ad_text → "Your Ideal Hotel in Switzerland. Compare Prices and Save on your Next Stay!"
display_url → "http://www.trivago.com"
Repeated on a second advertiser with the same outcome. Google does publish this. Our actor does not read it.
Action: get ad wording for text ads · Actor: automation-lab/google-ads-scraper 0 of 5 vs s-r/google-ads-transparency returns title + body + display URL
Reading the pictures is right for most ads, and wrong for text ads
Who said it
OCR is the only source of Google ad wording we have today — all 167 saved wordings came from it, not one from the actor. So it looked like OCR was simply the answer for Google.
What I found
It depends entirely on the ad's format, and the two cases have opposite answers:
FormatIn our databaseHas wording todayIs real wording available?
text7670 — via OCR Yes. Google publishes it; our actor misses it, s-r returns it
image33396 — via OCR No. Genuinely a picture — OCR is the only route
video181 — via OCR No. Same as image
Action: keep OCR for 351 image and video ads · add a text-ad pass for the other 76 · $0 for OCR
The limit setting does not limit the run
Who said it
maxAds: 10 reads like "this run will fetch at most 10 ads".
What I found
It means 10 ads per advertiser. I measured a run with ten Expedia IDs and maxAds: 30 — it came back with 300 items. So a brand with many IDs costs IDs × maxAds × price, and the real total can be far larger than the number you typed.
Action: cap a run · Actor: automation-lab/google-ads-scraper · 10 IDs × 30 = 300 items · not 30
Seventeen separate runs pay the start fee seventeen times
Who said it
Nothing stated it — it falls out of how the fees are structured.
What I found
The $0.005 fee is charged per run, while the limit is applied per advertiser. That combination is an opportunity: we have 17 advertiser IDs on file, and putting all 17 into one run pays the fee once instead of seventeen times. Same ads, same limits, same data.
Action: sweep all advertisers · Actor: automation-lab/google-ads-scraper · $0.085 in fees → $0.005 saves $0.08 a sweep
A better actor exists — but it cannot replace ours
Who said it
If one actor returns the wording and ours does not, the obvious move is to swap actors.
What I found
It cannot be a swap, for one blunt reason: s-r cannot find an advertiser by ID. I tried it on two different advertiser IDs and both returned 0 ads. Searching by brand name also returned 0. Only a domain lookup works. We store 17 advertiser IDs and no domains, so our entire pipeline is keyed on the one input it ignores. Worse, the domain lookup for Expedia returned advertiser AR12910272019299303425 — not one of the six Expedia IDs we track. Big brands run a separate ad account per country, so the two lookups return different ads. And even when it works, ad_text was filled on only 1 of 5 rows.
Action: replace the ads actor · Actor: s-r/google-ads-transparency · rejected as a replacement · accepted as a text-ad second pass
One alternative was tested and genuinely rejected
Who said it
solidcode/ads-transparency-scraper is the most-used Google ads actor on the store, so it looked like the natural upgrade.
What I found
0 of 8 ads carried any video information, and it has no way to look up an advertiser by ID at all — the same blocker as s-r. Recorded so it is not re-evaluated a third time.
Action: replace the ads actor · Actor: solidcode/ads-transparency-scraper · rejected twice
Google gives no call-to-action text at all, and Meta does
Who said it
The cta_text column being empty for Google looks like a collection gap on our side.
What I found
cta_text and display_format are empty on all 427 Google ads — while Meta fills them on 97 and 104 of 115. Same columns, same code, different platform. Google simply does not publish them.
Action: fill call-to-action · Actor: Google ads actor · 0/427 — not published · Meta: 97/115

Actors and data sets

Name, store title and statusReturns Returned but not usedWanted, but no source returns itCost
automation-lab/google-ads-scraper "Google Ads Scraper"live — the only Google ad source
InputadvertiserIds (we hold 17) or searchTerms, plus maxAds — which applies per advertiser, not per run.
ReturnsAd details — advertiser, creative id, format, first and last shown dates, image, media links, YouTube link. The four wording fields are returned empty every time.
advertiserIdadvertiserNameisVerifiedcreativeIdadFormatfirstShownlastShownimageUrlmediaUrlspreviewUrlregionyoutubeIdyoutubeWatchUrlvideoRecoveredBy · declared but always null: adTextheadlinebodycallToActiondestinationUrl isVerifiedcreativeIdregionpreviewUrl — no columns Ad copy — the actor's fault, not Google's. adText, headline, body, callToAction are declared and always null, including on ads whose adFormat is "Text", where Google does publish wording and s-r returns it · cta_text 0/427 and display_format 0/427 — these two Google really does not publish $0.001/ad
+ $0.005 per RUN
maxAds is per advertiser id
22.4 s
s-r/google-ads-transparency "Google Ads Transparency Scraper - Ad Library & Creatives" not currently used — proposed second pass for text ads only
Inputa website domain (advertiser IDs and brand-name search both return nothing), optionally filtered to format: text.
ReturnsAd details including the real wording — title, ad_text and display_url for text ads, plus advertiser, format, dates and image.
advertiser_idcreative_idadvertiser_nameformatfirst_shownlast_showndays_showntarget_domaindeeplink · the wording ours misses: titlead_textdescriptiondisplay_urlkeyword · image_urlpreview_urlad_group_idcustomer_id — not wired yet Advertiser IDs. advertiser_id returned 0 ads on two different IDs, and brand-name search returned 0 — only a domain lookup works, and we store 17 IDs and no domains. Its domain lookup also found a different Expedia account than the ones we track · ad_text filled on only 1 of 5 rows pay per result
$0.0076 for 5 text ads
21.5 s
tesseract.js local OCR, not a vendorlive — only wording source today
Inputa creative image file, already downloaded.
ReturnsThe words read out of the picture — line by line, with positions and a confidence score. Succeeds on about 39% of ads.
line-level text with positions and a confidence score, via the Worker API with { blocks: true } — The 351 image and video ads. OCR recovers copy on 167 of 427 — about 39% — and for images and video it stays the only route. On the 76 text ads it already gets 70, but as OCR'd picture text rather than clean fields $0 · local, no key, no API
solidcode/ads-transparency-scrapertrialled and rejected, v1.51
Inputsearch terms only — it has no advertiser-ID input at all.
ReturnsAd details, but 0 of 8 ads carried any video information.
ads— 0 of 8 ads carried any video field, and it has no advertiserId input at all — recorded so it is not re-evaluated a third time —
Bright Data
Input— nothing to send. Bright Data has no ad-library endpoint for any network.
Returns— nothing. This is why all four ad capabilities in the project have a single supplier and no backup.
—— No ad-library endpoint for any network. This is why all four ad capabilities in the project are single-tier —
TOTAL — measured test spend11 runs Limits applied: 5–10 ads per run, across 4 advertisers, comparing our actor against two alternatives on the same text ads $0.039
$0.009 first round
+ $0.030 ad-text comparison

What actually reaches the database, across all three ad networks

NetworkAdsad_copy_textLanding urlImageVideocta_text
google427167 — all from OCR427415180
meta1151131001155897
linkedin1818181890

Flow diagrams

current actor gives pictures, OCR gives words

One advertiser sweep.

1
Pick the input mode
advertiserIds where an id is on file (17 are), otherwise searchTerms — a fuzzy name search that can drift onto a similarly-named brand.
17 ids on file
2
Step: fetch ads from Google’s ad archive
What this isautomation-lab/google-ads-scraperApify actor
“Google Ads Scraper” — a rented program that reads Google’s public Ads Transparency Center. The only one that accepts an advertiser ID, which is how our whole pipeline is keyed.
The $0.005 fee is charged per run, so a 17-advertiser sweep pays it 17 times.
$0.001/ad + $0.005/run22.4 smaxAds is per id
3
Payload arrives with adText, headline, body, callToAction all null
Declared by the schema, never populated — even on text ads, where Google does publish wording.
0 of 5 on text ads0/427 cta_text
4
Step: read the words out of the ad picture
What this istesseract.jsfree, runs on our server
“open-source text recognition” — not a vendor and not a rented program — a text-recognition library running on our own machine. No key, no account, no bill.
Worker API, { blocks: true } for line positions. Writes ad_copy_source = 'ocr'. Doing picture-reading even on the 76 text ads, whose words are available as clean fields.
$0167 of 427 — 39%
A 17-advertiser sweep pays $0.085 in run fees alone — and 76 text ads get their wording guessed from a picture when it could be read directly.
Content Agent Dashboard · vendor audit · BRONZE plan rates · total test spend $0.40