Facebook Post Search Scraper: Keyword and Hashtag Posts
Pricing
from $1.80 / 1,000 posts
Facebook Post Search Scraper: Keyword and Hashtag Posts
Search public Facebook posts by keyword or hashtag: post text, author page, date, reactions by type, comment count, share count, media and URL. Top or latest posts, date range and location filters. No login, no cookies. One row per post.
Pricing
from $1.80 / 1,000 posts
Rating
0.0
(0)
Developer
The Mine Works
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Security
Limited permissionsShare
From The Mine Works, makers of Threads Scraper and B2B Leads Finder, with over 295,000 runs across 310+ public actors.
Updated 4 Nov 2026: first release. Keyword and hashtag search of public Facebook posts, top or latest order, date range, location, one flat row per post with text, author, date, reactions by type, comment count, share count, media and link. Bookmark this Actor on its Store page so it is one click away next time.
Why choose this actor?
- Search Facebook posts the way you search Facebook. Type words or a hashtag and get the public posts Facebook lists for them: from Pages, public profiles and public groups. Run many keywords at once. A post found by two keywords is delivered and charged once.
- Every number in its own column.
reactions_count,reactionssplit by type (like, love, care, haha, wow, sad, angry),comments_count,shares_count, andvideo_viewson videos and reels, plus the full post text, the exact date and the post link. - A filter for what you really asked for. Facebook's search also returns related posts that do not contain your words. Each row has
keyword_in_text, andonlyPostsContainingKeyworddrops the rest for free. For a brand name this is the difference between mentions and noise. - Honest about depth. Facebook ends a logged out search list on its own. On 12 keywords we measured 71 to 303 posts per keyword in top order. The run summary lists, per keyword, how many posts Facebook gave and why the list stopped. To go further, add related keywords.
- Empty runs stay cheap. There is no warm-up page: a run's first request is already the first page of results. A keyword with no posts ends after that one request and you pay nothing, and no start fee, when no post is delivered.
- No Facebook account. No login, no cookies of yours, no browser and no CAPTCHA solving.
Part of The Mine Works Social media and video family: Threads Scraper, Reddit Scraper, Threads Search Scraper, Instagram Profile Scraper, Instagram Followers & Following, Reddit Search Scraper.
Try it in one minute
Paste this into the JSON tab of the input page. It returns 20 posts. It took 7 seconds in our test.
{"keywords": ["electric cars"],"maxPostsPerKeyword": 20}
Apify's free plan includes $5 of credit every month, which covers about 1,380 posts at this actor's price.
Copy to your AI assistant
themineworks/facebook-post-search-scraper on Apify. Searches public Facebook posts by keyword or hashtag, logged out, and returns one flat row per post. Call ApifyClient("TOKEN").actor("themineworks/facebook-post-search-scraper").call(run_input={"keywords": ["electric cars"], "maxPostsPerKeyword": 50}), then client.dataset(run["defaultDatasetId"]).list_items().items. Give keywords (list of words, hashtags or Facebook search links, up to 200) or query (one string). Optional: maxPostsPerKeyword (default 50, 1 to 1000), sortBy (top or latest), startDate and endDate (YYYY-MM-DD), location (city name or numeric Facebook place id), onlyPostsContainingKeyword (boolean, drops posts without the exact phrase for free). Post rows have no _type field and carry post_id, post_url, text, created_at, timestamp, author_name, author_id, author_url, author_picture_url, author_type, group_id, group_name, group_url, post_type, reactions_count, reactions, comments_count, shares_count, video_views, media, media_urls, link_url, link_title, link_domain, link_image, is_reshare, shared_post, place_id, place_name, sponsored, keyword, keyword_in_text, sort, position, scraped_at. Rows with _type are summary, info or error rows and are never charged. Priced per post delivered plus a small flat fee per run, charged only after the first post is delivered.
Key features
- Top or latest.
topis Facebook's own order.latestasks for recent posts first: in our test on "electric cars" every post was from the last 6 days. It returns a shorter list than top. - Date range.
startDateandendDatego to Facebook, and any post outside the range it returns anyway is dropped for free. In our test Facebook returned 12 such posts out of 45, and all 30 delivered posts were inside the range. - Location. A city name or a Facebook place id. Facebook uses it as a preference for posts tagged there, not as a strict filter;
place_nameon each row shows the tag when there is one. The run summary names the city it used inlocation_resolved. - Keywords and hashtags.
tesla,real estate agent,#electricvehicles, or a pasted Facebook search or hashtag link. Any language. - Group posts named. Posts from public groups carry
group_id,group_nameandgroup_urlnext to the author. - Reshares linked.
is_reshareandshared_postgive the original post's id, link, author and date. - One record or a thousand.
querytakes one keyword for a call per record from Clay, n8n or an AI agent.keywordstakes a list, and three run at the same time. - Stops cleanly. The run stops before its time limit, on your max cost, when Facebook refuses searches, or when pages bring nothing new, and it keeps every row it read.
How to use it
Brand and competitor monitoring
Run your brand names once a day in latest order, keeping only posts with the exact name. Compare on post_id to see what is new.
{"keywords": ["your brand", "your competitor"],"sortBy": "latest","onlyPostsContainingKeyword": true,"maxPostsPerKeyword": 100}
Social listening for one call in a pipeline
From Clay, n8n or an agent, call the actor once per record with query. A keyword that has no posts costs one small request and no fee.
{"query": "acme plumbing austin","maxPostsPerKeyword": 10}
Lead signals by city
Search words people use when they are about to buy, in one city, in one month. Sort the rows by comments_count to find the live threads.
{"keywords": ["looking for a realtor", "recommend a dentist"],"location": "Austin, Texas","startDate": "2026-10-01","endDate": "2026-10-31","maxPostsPerKeyword": 100}
Sentiment and topic datasets
Pull 200 posts per keyword across ten related keywords, then run your own classifier on text. reactions gives a ready made signal, and sad and angry counts often say more than the text.
Content research
Search your topic in top order and sort by shares_count. post_type tells you which format earned the shares: photo, album, video, reel, link or text.
Input parameters
| Parameter | Type | Default | What it does |
|---|---|---|---|
keywords | array of strings | empty | Words, hashtags or Facebook search links, one per line. Up to 200. |
query | string | empty | One keyword, for calling the actor once per record. |
maxPostsPerKeyword | integer | 50 | Most posts per keyword, 1 to 1,000. Facebook usually ends the list first. |
sortBy | string | top | top or latest. |
startDate | string | empty | Posts from this date on, YYYY-MM-DD. |
endDate | string | empty | Posts up to and including this date, YYYY-MM-DD. |
location | string | empty | City name or numeric Facebook place id. A preference, not a strict filter. |
onlyPostsContainingKeyword | boolean | false | Keep only posts whose text has the exact phrase; the rest are dropped for free. |
Give keywords, query or both.
What data do you get?
| Field | What it is |
|---|---|
post_id | Facebook id of the post |
post_url | Link to the post |
text | Full post text with line breaks; absent on a photo or video with no caption |
created_at | Publish date and time, ISO 8601 UTC |
timestamp | The same moment as Unix seconds |
author_name | Name of the Page or profile that posted |
author_id | Facebook id of the Page or profile (a pfbid token for some profiles) |
author_url | Link to the Page or profile, when Facebook gives one |
author_picture_url | Profile picture link (expires after a few days) |
author_type | Facebook's type: usually User, which includes modern Pages |
group_id, group_name, group_url | The public group, when the post is a group post |
post_type | text, photo, album, video, reel, link or shared |
reactions_count | All reactions |
reactions | Reactions by type that Facebook shows |
comments_count | Comments |
shares_count | Shares |
video_views | Views, on videos and reels where Facebook shows them |
media | Photos and videos: type, url, thumbnail, width, height, alt, id, duration |
media_urls | Just the image and thumbnail links, for a sheet |
link_url, link_title, link_domain, link_image | The shared link on link posts |
is_reshare, shared_post | Whether it shares another post, and that post's id, link, author, text and date |
place_id, place_name | The place tagged in the post |
sponsored | true when Facebook marks the post as paid |
keyword | The keyword that found the post |
keyword_in_text | true when the text has the keyword as an exact phrase |
sort | top or latest |
position | Position among the delivered posts of its keyword |
scraped_at | When the row was read |
Stable fields for automations
These were present in every post row of our test run (2,216 rows from 12 keywords), and their names will not change:
| Field | What it is |
|---|---|
post_id | The key to store and join on |
post_url | Open the post |
created_at | Publish date |
author_name, author_id | Who posted |
reactions_count, comments_count, shares_count | Engagement |
post_type | Format |
keyword, keyword_in_text | What found it and whether the words are in it |
Empty values are left out of a row rather than sent as null, so a text post has no media_urls, and a post outside a group has no group_id.
Output examples
A post from a Page:
{"post_id": "1566219672210300","post_url": "https://www.facebook.com/LucidMotors/posts/pfbid02t74ZFgJrQRX1dgDeAoW2efjEzvG6B4neS6Wzd8QHHsDbKPwLL77A5DRq2ztMPbdfl","text": "Car and Driver ranked Lucid first among car brands the outlet has tested over the years, earning a 10/10 rating based on perfect scores for both Lucid Air and Lucid Gravity...","created_at": "2026-11-02T21:38:15.000Z","timestamp": 1793655495,"author_name": "Lucid Motors","author_id": "100064668460659","author_url": "https://www.facebook.com/LucidMotors","author_type": "User","post_type": "photo","reactions_count": 197,"reactions": { "like": 168, "love": 26, "wow": 2, "care": 1 },"comments_count": 30,"shares_count": 10,"media": [{ "type": "photo", "url": "https://scontent-lga3-3.xx.fbcdn.net/v/...", "width": 2048, "height": 1536, "alt": "May be an image of car, road and text", "id": "1566219572210310" }],"media_urls": ["https://scontent-lga3-3.xx.fbcdn.net/v/..."],"is_reshare": false,"sponsored": false,"keyword": "electric cars","keyword_in_text": false,"sort": "top","position": 1,"scraped_at": "2026-11-04T14:00:12.000Z"}
Run summary (the last row of each run, never charged, also in the OUTPUT record):
{"_type": "summary","keywords_requested": 1,"keywords_read": 1,"pages_read": 2,"posts_found": 23,"posts_delivered": 20,"charged_for": 20,"per_keyword": [{ "keyword": "electric cars", "pages": 2, "posts_found": 23, "posts_delivered": 20, "stopped": "max_posts_reached" }]}
stopped is max_posts_reached (your limit), end_of_results (Facebook's list ended), no_new_posts, max_cost, time or a refusal reason.
Pricing
Pay per event: you pay for the posts you receive, plus a flat $0.001 per run, whatever memory you choose.
| Event | When it is charged | Free plan | Bronze (Starter) | Silver (Scale) | Gold (Business) |
|---|---|---|---|---|---|
post-scraped | Once per post row stored in your dataset | $3.60 per 1,000 | $2.70 per 1,000 | $2.25 per 1,000 | $1.80 per 1,000 |
run-start | Once per run, after the first post is delivered | $0.001 | $0.001 | $0.001 | $0.001 |
The price of one post is the price per 1,000 divided by 1,000.
Never charged:
- a keyword with no posts, and a run that delivers no post: the start fee is charged only after the first post reaches your dataset;
- a run Facebook refuses;
- a post that a second keyword of the same run finds again;
- posts outside your date range, and posts dropped by
onlyPostsContainingKeyword; - the summary, info and error rows;
- anything past your "Max cost per run". The actor checks the budget before each batch of rows and stops while the total is still below your limit, so the run ends SUCCEEDED with a partial result and a status message saying so.
Run it on a schedule
- Open the actor in Apify Console, set your input and click Save as a new task.
- In the task, open Schedules, click Add schedule and pick how often (every morning, every Monday at 08:00 and so on).
- Use
sortByset tolatestand compare runs onpost_idto see what is new. - Optional: add an integration (Google Sheets, Slack, a webhook) so each run lands where your team works.
FAQ
What does this actor read?
Facebook's public post search, as a visitor who is not logged in sees it: public posts from Pages, public profiles and public groups. It does not log in and cannot see private groups, friends only posts or anything behind a sign in.
How many posts can I get per keyword?
Facebook decides. It ends a logged out search list on its own: we measured 71 to 303 posts per keyword in top order on 12 keywords, and a shorter list in latest order. The summary shows where each list stopped. To collect more, add related keywords; a post found twice is charged once.
Why do some posts not contain my keyword?
Facebook's search matches related words and topics, not only your exact phrase. In our test about two thirds of the posts contained the exact keyword. Turn on onlyPostsContainingKeyword to keep just those. Dropped posts are free; the run takes longer because it reads more pages.
Is the date filter exact?
The rows you get are. Facebook mostly honours the range and sometimes returns posts outside it, and the actor drops those for free.
Is the location filter strict?
No. Facebook treats it as a preference for posts tagged in that place, so some results have no tag. Filter on place_name if you need only tagged posts.
Why is author_url missing on some rows?
Some personal profiles have no public link for a logged out visitor. author_id and author_name are still there, and when the post link carries the profile's name, we build the link from it.
Why is the count different from what I see when logged in?
Facebook personalises search for accounts. This actor sees what a logged out visitor sees.
How long does a run take?
Each request brings about 11 posts and takes 1 to 5 seconds, and three keywords run at the same time. 20 posts took 7 seconds, and 2,216 posts from 12 keywords took about 10 minutes in our test.
Do I need an account, cookies or a proxy?
No. Everything is included. You only need an Apify account.
Which actor should I use for the comments of these posts?
Feed post_url into Facebook Comments Scraper to get the comments and replies.
Which formats can I download?
JSON, CSV, Excel, XML, RSS and HTML from the run's Storage tab or through the API. The dataset has two ready views: Posts, and Authors and links. In CSV and Excel, reactions and media are flattened into columns such as reactions/like and media/0/url.
Can I use it from Claude, ChatGPT or Cursor (MCP)?
Yes, through Apify's MCP server. Connector URL: https://mcp.apify.com/?tools=themineworks/facebook-post-search-scraper
- Claude: Settings > Connectors > Add custom connector, paste the URL, sign in with Apify.
- ChatGPT: turn on developer mode, add an MCP connector with the URL, sign in with Apify.
- Cursor or VS Code: add it as an HTTP MCP server with that URL.
- Claude Code:
claude mcp add -t http facebook-post-search-scraper "https://mcp.apify.com/?tools=themineworks/facebook-post-search-scraper"
Is it legal to scrape Facebook posts?
The actor reads only public posts that anyone can see without logging in. Posts can contain personal data, so you are responsible for how you use the data, including Facebook's terms and data protection law such as GDPR and CCPA. This is general information, not legal advice.
Integrations
- Google Sheets: send each run's posts to a sheet with Apify's Google Sheets integration; one row per post fits a sheet as is.
- Make, Zapier and n8n: start a run and read its dataset with the Apify apps and nodes, for example "new posts on our brand every morning to Slack".
- Webhooks: have Apify call your URL when a run succeeds, then fetch the dataset.
- API and SDKs: run it from Python or JavaScript with the Apify client, or with a plain HTTP call (see "Copy to your AI assistant" above).
- MCP clients: Claude, ChatGPT, Cursor and VS Code can run it as a tool through the connector URL in the FAQ.
More from The Mine Works
Social media and video
- Threads Scraper
- Reddit Scraper
- Threads Search Scraper
- Instagram Profile Scraper
- Instagram Followers & Following
- Reddit Search Scraper
- Twitter / X Scraper
- YouTube Transcript
- Xiaohongshu (RED) Scraper
- Telegram Channel Scraper
- Telegram Channel Finder
- Pinterest Profile Scraper
Leads and business directories
Marketing, SEO and reviews
Real estate
Science, health and government data
Jobs and hiring
Company and business data
E-commerce and marketplaces
Food and local services
Developer and AI tools
More tools
Support
Found a keyword that returns far fewer posts than expected, or a field that comes back empty? Open an issue in the Issues tab with the input and the run ID, and we will look at it. For a field you need that is not here, say so in the same place.
Search public Facebook posts by keyword or hashtag and get every post back as one row, with text, author, date, reactions by type, comments, shares, media and link, no login.

