facebook-hashtag-search-scraper-top-posts-engagement-ranking
Pricing
from $4.99 / 1,000 results
facebook-hashtag-search-scraper-top-posts-engagement-ranking
Scrape Facebook hashtag search results — posts, reels, reactions, comments, shares, attachments and full Reels metadata. Built for speed and scale.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
Facebook Hashtag Scraper — Posts, Reactions and Engagement Rank
Facebook Hashtag Scraper collects public posts from any Facebook hashtag feed and returns them as structured JSON — author, caption text, reaction breakdown, comment and share counts, video views and media attachments. Turn on engagement scoring and every post also gets a totalEngagement score, an engagementRank and a topReactionType, so the best-performing posts under a hashtag surface first instead of just the newest ones. It's built for social media analysts, brand and community managers, and researchers who need to know what's actually resonating under a tag, not just what was posted last.
What is Facebook Hashtag Scraper?
Facebook Hashtag Scraper is an Apify Actor that pulls the post feed behind one or more Facebook hashtags and shapes it into a typed dataset, with an optional scoring pass that ranks posts by engagement. Facebook only serves the hashtag feed to a logged-in session, so the Actor requires your own Facebook session cookie (c_user + xs, or the combined fbCookie string) — there is no anonymous or developer-account path into this feed.
- Discovery by hashtag: plain tags (
travel,#travel) or full hashtag URLs, any mix, in one run - Core identifying fields on every post:
postId,user,url,text,time/timestamp - Secondary engagement data straight from Facebook: reaction breakdown,
commentsCount,sharesCount,videoViewCount - Derived analytics when scoring is on:
totalEngagement,engagementRate,topReactionType,engagementRank - Real filters: a minimum-engagement threshold and a newer-than date window (absolute date or relative window)
- Download the dataset as JSON, JSONL, CSV, Excel, HTML table or XML, or read it straight through the Apify API
What data can I extract with Facebook Hashtag Scraper?
Every post is one dataset row carrying the base Facebook fields plus, when engagement scoring is on, seven derived analytics columns.
| Field | Example Value | Use Case |
|---|---|---|
searchQuery | "streetfood" | Which hashtag this row came from, when ranking several tags in one run |
postId | "1150692399746997" | Facebook's post identifier |
user | {"name":"Jane Doe","id":"100012345678901","url":"https://www.facebook.com/profile.php?id=100012345678901","avatar":"https://scontent..."} | Attribute the post to its author and link back to their profile |
url | "https://www.facebook.com/1150692399746997" | Direct link to the post |
text | "Best tacos in town! #streetfood" | Caption text for keyword/topic analysis |
topReactions | {"Like":120,"Love":34,"Haha":5} | Per-reaction-type counts, Facebook's own labels |
commentsCount | 42 | Comment volume |
sharesCount | 12 | Share volume — the strongest virality signal |
videoViewCount | 8500 | View count on video posts (0 on non-video posts) |
time | "2026-07-20 14:03:00" | Post time as Facebook renders it (naive-local, not timezone-safe) |
timestamp | 1753020180 | Unix seconds — the source of truth behind every date field |
attachments | [{"target":{"__typename":"Photo","id":"..."},"media":{...}}] | Attached photos, videos, shares or albums with Facebook's own typed metadata |
engagementRank | 1 | Position by totalEngagement among all posts collected for that hashtag (1 = highest) |
totalEngagement | 178 | sum(topReactions) + commentsCount + sharesCount |
engagementRate | 2.0941 | totalEngagement / videoViewCount * 100, video posts only |
totalReactions | 159 | Sum of topReactions values |
topReactionType | "Like" | The single most-used reaction on the post |
passedEngagementFilter | true | Whether the post met minTotalEngagement — this also decides whether the row is billed |
publishedAt | "2026-07-20T14:03:00Z" | UTC ISO-8601 timestamp, derived from timestamp — use this instead of time for any cross-timezone sorting |
Engagement and reaction data
totalEngagement, engagementRate, topReactionType, engagementRank and passedEngagementFilter are all derived from data Facebook already returned on the post — no extra requests are made to compute them. topReactionType is simply whichever key in topReactions has the highest count; reaction names come through as Facebook's own localized labels (Like, Love, Haha, Wow, Sad, Angry, Care), not a fixed enum the Actor defines. engagementRate is set only when videoViewCount > 0 — for a non-video post there is no view denominator, so the field is null rather than a misleading 0. Turn computeEngagementScore off and all seven of these keys stay in the row, present but null, so the dataset shape never changes between runs.
Targeting and filtering data
onlyPostsNewerThan filters on the post's real timestamp, so it works whether you pass an absolute date or a relative window. minTotalEngagement filters on totalEngagement but does not drop anything below it — matching rows stay in the dataset flagged passedEngagementFilter=false, which is the field to threshold on downstream. searchQuery lets you segment a multi-hashtag run back out by tag before you do anything else with the rows.
Why not build this yourself?
Facebook does not publish a hashtag-search API for third parties — the Graph API covers content your own app or Page manages, not an arbitrary public hashtag feed, so there is no official endpoint to compare this Actor against.
Building it yourself means first reverse-engineering a moving target: the hashtag feed's GraphQL layer runs on persisted queries, so every session needs a fresh fb_dtsg token, an lsd token and the numeric doc_ids for SearchCometResultsInitialResultsQuery and SearchCometResultsPaginatedResultsQuery, all pulled out of the page's inline HTML and JS bundles rather than a documented request format. On top of that, Facebook ties a session's trust to its exit IP — replaying a cookie from a datacenter IP, or scattering one session's calls across many residential IPs, is what typically gets an account checkpoint-locked — and the feed silently serves a logged-out or checkpoint page instead of an error when a session is bad. Facebook Hashtag Scraper handles all of it: it extracts the session tokens per run, pins one sticky residential exit IP for the whole run and rotates only on a hard block, and detects the checkpoint/logged-out pages explicitly so a bad cookie fails fast with an actionable message instead of a silent empty result.
How to use data extracted from Facebook hashtag posts
- 📊 Social media and brand teams run their brand or campaign hashtag through
searchQueries, sort ontotalEngagement, and pull the topengagementRankposts into a weekly report of what actually landed with the audience. - 🏢 Agencies running the same set of client and competitor hashtags on a schedule diff
totalEngagementandtopReactionTypeweek over week to show clients whether sentiment and reach are trending up or down. - 🔬 Market researchers set
onlyPostsNewerThanto a recent window andminTotalEngagementto a real-traction floor, then readtextandtopReactionsacross the surviving posts to map what a community is actually saying about a topic right now, not just what's loudest. - 🤖 AI agents and automated pipelines call the Actor as a standard Apify run, filter on
passedEngagementFilter, and feedtextplus the engagement fields into a summarizer or a trend-monitoring agent without any manual scoring step.
🔼 Input sample
Required: searchQueries.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
searchQueries | Yes | array | One or more Facebook hashtags to collect and rank. Plain tags (marketing, #travel) or full hashtag URLs (https://www.facebook.com/hashtag/travel) both work. Default ["football"]. | ["fitness", "streetfood"] |
maxItems | No | integer | How many posts to pull from each hashtag before scoring and ranking. Facebook's hashtag feed tops out around ~200 posts per tag. Minimum 1, maximum 10000, default 10. | 50 |
computeEngagementScore | No | boolean | Add the derived columns to every post: totalEngagement, engagementRate, topReactionType, engagementRank and publishedAt. Turn off to return raw posts only. Default true. | true |
sortByEngagement | No | boolean | Output posts ordered highest-engagement first instead of Facebook's feed order. engagementRank is always filled regardless. Default true. | true |
minTotalEngagement | No | integer | Only charge for posts whose totalEngagement is at least this value; lower-engagement posts are still returned but flagged passedEngagementFilter=false and are not billed. Minimum 0, default 0 (keep all). | 100 |
onlyPostsNewerThan | No | string | Drop posts older than this cutoff. Accepts an absolute date (2026-06-01) or a relative window (7 days, 2 weeks, 1 month). Leave empty to keep posts of any age. | "30 days" |
fbCookie | No | string (secret) | Your Facebook session cookie as a single string, e.g. c_user=100012345678901; xs=34%3Aabcd.... Copy the c_user and xs values from DevTools → Application → Cookies → www.facebook.com. Kept secret; never stored. If set it fills c_user/xs below automatically. | "c_user=100012345678901; xs=34%3Aabcd..." |
c_user | No | string | The c_user Facebook cookie (your numeric user ID). Optional if you supplied the combined cookie string above. | "100012345678901" |
xs | No | string (secret) | The xs Facebook cookie (URL-encoded session token). Optional if you supplied the combined cookie string above. Treated as a secret — it grants access to your account. | "34%3Aabcd1234..." |
proxyConfiguration | No | object | By default the actor pins a sticky residential IP (datacenter IPs are blocked by Facebook) and rotates on hard blocks. Override here to force your own proxy group. Default {"useApifyProxy": false}. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
Example input
{"searchQueries": ["streetfood", "foodtruck"],"maxItems": 100,"computeEngagementScore": true,"sortByEngagement": true,"minTotalEngagement": 50,"onlyPostsNewerThan": "30 days","fbCookie": "c_user=100012345678901; xs=34%3Aabcd...","proxyConfiguration": { "useApifyProxy": false }}
Common pitfall: the Actor needs both c_user and xs — supplied directly or parsed out of fbCookie — or it cannot reach the feed at all. Explicit c_user/xs values always win over whatever fbCookie would have filled in. Without a working session, no hashtag is scraped: the run finishes successfully with a single, uncharged diagnostic row explaining that credentials are required, instead of failing or returning nothing with no explanation.
🔽 Output sample
⚠️ Facebook's hashtag feed itself tops out around ~200 posts per tag — raising maxItems past that will not pull more posts, because that ceiling is Facebook's, not the Actor's. Typed, normalized JSON, one row per post, same 19 keys every run. Export as JSON, CSV, Excel, HTML table or XML, or read the dataset through the Apify API.
Example output
{"searchQuery": "streetfood","postId": "1150692399746997","user": {"name": "Jane Doe","id": "100012345678901","url": "https://www.facebook.com/profile.php?id=100012345678901","avatar": "https://scontent.xx.fbcdn.net/v/t39.30808-1/avatar.jpg"},"url": "https://www.facebook.com/1150692399746997","text": "Best tacos in town! #streetfood","topReactions": { "Like": 120, "Love": 34, "Haha": 5 },"commentsCount": 42,"sharesCount": 12,"videoViewCount": 8500,"time": "2026-07-20 14:03:00","timestamp": 1753020180,"attachments": [{"deduplication_key": "abc123","target": { "__typename": "Photo", "id": "1150688623080708" },"__typename": "StoryAttachment","style_list": ["photo", "fallback"],"styles": {},"media": {},"all_subattachments": { "nodes": [] }}],"engagementRank": 1,"totalEngagement": 178,"engagementRate": 2.0941,"totalReactions": 159,"topReactionType": "Like","passedEngagementFilter": true,"publishedAt": "2026-07-20T14:03:00Z"}
If a hashtag yields zero posts — an unusual tag, expired cookies, a locked account, or a transient Facebook block — the run still finishes successfully with one diagnostic row (fields status and message in place of the usual data) instead of failing, and that row is never charged.
How do you filter and target specific posts?
Two axes decide what lands in your dataset: how much you collect, and what counts as worth keeping. maxItems sets how many posts are pulled per hashtag before scoring — but Facebook's own feed ceiling of roughly 200 posts per tag caps this in practice regardless of how high you set it, so raising it past that point buys nothing. onlyPostsNewerThan narrows by time, accepting either an absolute date or a relative window like 7 days or 2 weeks — posts with no readable timestamp are kept rather than dropped, so a parsing gap never silently loses data. minTotalEngagement is the quality threshold, but it's an accounting filter, not a drop filter: posts below it stay in the dataset with passedEngagementFilter=false and are simply not billed, so you can audit what got filtered without paying for it. To isolate only the rows Facebook actually charged you for, filter on passedEngagementFilter !== false (equivalent to === true here, since the field is only ever null when computeEngagementScore is off, in which case every row is charged).
{ "searchQueries": ["marketing"], "maxItems": 200, "onlyPostsNewerThan": "7 days" }
{ "searchQueries": ["fitness"], "minTotalEngagement": 500, "sortByEngagement": true }
{ "searchQueries": ["travel", "wanderlust"], "onlyPostsNewerThan": "2026-06-01", "computeEngagementScore": true }
▶️ Want to try other Facebook scrapers?
| Scraper Name | What it extracts |
|---|---|
| Facebook Search Scraper by Hashtag | Pages posting under a hashtag, plus each Page's full profile |
| Facebook Group Engagement Analyzer | Ranks a Facebook Group's own posts by engagement score |
| Facebook Page Content Strategy Scraper | A Page's content-type mix, hashtags, mentions and CTAs |
| Facebook Pages Scraper with Ad Library Activity | Public Pages plus their live Ad Library activity |
| Instagram Reels Hashtag Scraper | Instagram Reels by hashtag with engagement ranking |
| TikTok Trending Hashtags Scraper | TikTok trending hashtags with daily growth history |
How to extract Facebook hashtag data programmatically
Facebook Hashtag Scraper runs as a standard Apify Actor — one authenticated call through the Apify API, structured JSON back, no scraping infrastructure of your own to run.
Python example
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<YOUR_USERNAME>/facebook-hashtag-search-scraper-top-posts-engagement-ranking").call(run_input={"searchQueries": ["streetfood"],"maxItems": 100,"minTotalEngagement": 50,"fbCookie": "c_user=100012345678901; xs=34%3Aabcd...",})for post in client.dataset(run["defaultDatasetId"]).iterate_items():if post.get("passedEngagementFilter") is not False:print(post["text"][:60], post["totalEngagement"], post["topReactionType"])
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.
Export to spreadsheets or CRM
Download the dataset as CSV directly from the Apify Console, or pull it through the API and map text, totalEngagement, engagementRank and url into a spreadsheet or CRM import — user.name and user.url map cleanly to a contact/author column for lead or influencer tracking.
Is it legal to scrape Facebook hashtag data?
Scraping content that a logged-in visitor can already see on Facebook's own hashtag feed is generally treated as accessing published content, not breaching a technical barrier — this Actor surfaces only what that feed already shows to a signed-in session, nothing behind a private group or friends-only wall.
Hashtag posts are personal data in the general sense: captions, reactions and profile links are attributed to whoever posted, whether an individual profile or a business Page, so GDPR and CCPA framing applies to any storage or reuse of the collected rows — you need a lawful basis to retain and process personal data pulled this way, and should minimize what you keep to what your use case actually needs.
Consult legal counsel for commercial applications involving bulk storage of personal data.
❓ Frequently asked questions
What if a hashtag has zero recent posts?
The run still finishes successfully. Instead of an empty or failed run, the Actor pushes one uncharged diagnostic row explaining why — an unusual or empty hashtag, a transient Facebook block, or invalid credentials — so you always know why the dataset is empty rather than having to guess.
Can I get engagement data along with the posts?
Yes, and it's on by default. computeEngagementScore=true adds totalEngagement, engagementRate, topReactionType, engagementRank and publishedAt to every post at no extra request — all derived from fields Facebook already returned in the same response.
How accurate is the engagement data?
The Actor returns reaction, comment and share counts exactly as Facebook's feed reports them at request time. Accuracy depends on Facebook's own count at that moment, which can keep climbing after you scrape it — re-run periodically if you need current numbers rather than a one-time snapshot.
How many posts can I get per run?
maxItems accepts 1 to 10,000, but Facebook's hashtag feed itself tops out around ~200 posts per tag regardless of what you set — that ceiling belongs to Facebook, not the Actor, so there's no value in setting maxItems far above it for a single hashtag.
How does the minimum-engagement filter actually work?
minTotalEngagement doesn't drop low-engagement posts — it flags them. Posts below your threshold still appear in the dataset with passedEngagementFilter=false, but they're excluded from billing rather than from the output, so you can see everything Facebook returned while only paying for the posts that cleared your bar.
Does Facebook Hashtag Scraper work with Claude, ChatGPT and other AI agent frameworks?
Yes. It is callable as a standard HTTP endpoint through the Apify API, so any agent framework that can make a request — LangChain, CrewAI, n8n, a custom tool definition — can invoke it and receive typed JSON directly.
How does Facebook Hashtag Scraper compare to other Facebook post scrapers?
Checked on the Apify Store as observed on 2026-07-26: scraper_one/facebook-posts-search documents keyword and location search returning post URL, reactions, comments and shares, with no engagement scoring or ranking documented. easyapi/facebook-posts-search-scraper documents a similar keyword-search field set (likes, comments, shares) with no ranking or filtering beyond a result-count cap. scrapeforge/facebook-search-posts documents the broadest search surface — six content types including posts, pages and videos — but ranking, engagement scoring and an uncharged-row filter mechanic are not documented on any of the three. Facebook Hashtag Scraper's difference is scoring and ranking the posts it collects — totalEngagement, engagementRank, topReactionType — and a minTotalEngagement threshold that keeps low-performing posts visible without billing for them.
Can I use Facebook Hashtag Scraper without a Facebook API key or developer account?
Yes — and you have to, since there is no Facebook developer API for the hashtag feed to authenticate against. What you supply instead is your own Facebook session: the c_user and xs cookie values from a logged-in browser session (directly, or combined in fbCookie), which the Actor uses only to request the feed and never persists in the dataset.
Conclusion
Facebook Hashtag Scraper turns any Facebook hashtag feed into a ranked, structured dataset — posts scored on totalEngagement, ordered by engagementRank, and filterable by a real minimum-engagement threshold that never bills for the rows it excludes. It's built for social teams, agencies and researchers who need to find what's actually working under a hashtag, not just what's newest. Open Facebook Hashtag Scraper on Apify, supply your Facebook session cookie and a hashtag, and start the run.