Facebook Post Search Scraper: Keyword and Hashtag Posts avatar

Facebook Post Search Scraper: Keyword and Hashtag Posts

Pricing

from $1.80 / 1,000 posts

Go to Apify Store
Facebook Post Search Scraper: Keyword and Hashtag 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

The Mine Works

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

3 days ago

Last modified

Security

Limited permissions

Share

20 Facebook posts by keyword with reactions, comments and shares in 7 seconds

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, reactions split by type (like, love, care, haha, wow, sad, angry), comments_count, shares_count, and video_views on 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, and onlyPostsContainingKeyword drops 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.

Run it on Apify

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. top is Facebook's own order. latest asks 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. startDate and endDate go 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_name on each row shows the tag when there is one. The run summary names the city it used in location_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_name and group_url next to the author.
  • Reshares linked. is_reshare and shared_post give the original post's id, link, author and date.
  • One record or a thousand. query takes one keyword for a call per record from Clay, n8n or an AI agent. keywords takes 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

ParameterTypeDefaultWhat it does
keywordsarray of stringsemptyWords, hashtags or Facebook search links, one per line. Up to 200.
querystringemptyOne keyword, for calling the actor once per record.
maxPostsPerKeywordinteger50Most posts per keyword, 1 to 1,000. Facebook usually ends the list first.
sortBystringtoptop or latest.
startDatestringemptyPosts from this date on, YYYY-MM-DD.
endDatestringemptyPosts up to and including this date, YYYY-MM-DD.
locationstringemptyCity name or numeric Facebook place id. A preference, not a strict filter.
onlyPostsContainingKeywordbooleanfalseKeep only posts whose text has the exact phrase; the rest are dropped for free.

Give keywords, query or both.

What data do you get?

FieldWhat it is
post_idFacebook id of the post
post_urlLink to the post
textFull post text with line breaks; absent on a photo or video with no caption
created_atPublish date and time, ISO 8601 UTC
timestampThe same moment as Unix seconds
author_nameName of the Page or profile that posted
author_idFacebook id of the Page or profile (a pfbid token for some profiles)
author_urlLink to the Page or profile, when Facebook gives one
author_picture_urlProfile picture link (expires after a few days)
author_typeFacebook's type: usually User, which includes modern Pages
group_id, group_name, group_urlThe public group, when the post is a group post
post_typetext, photo, album, video, reel, link or shared
reactions_countAll reactions
reactionsReactions by type that Facebook shows
comments_countComments
shares_countShares
video_viewsViews, on videos and reels where Facebook shows them
mediaPhotos and videos: type, url, thumbnail, width, height, alt, id, duration
media_urlsJust the image and thumbnail links, for a sheet
link_url, link_title, link_domain, link_imageThe shared link on link posts
is_reshare, shared_postWhether it shares another post, and that post's id, link, author, text and date
place_id, place_nameThe place tagged in the post
sponsoredtrue when Facebook marks the post as paid
keywordThe keyword that found the post
keyword_in_texttrue when the text has the keyword as an exact phrase
sorttop or latest
positionPosition among the delivered posts of its keyword
scraped_atWhen 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:

FieldWhat it is
post_idThe key to store and join on
post_urlOpen the post
created_atPublish date
author_name, author_idWho posted
reactions_count, comments_count, shares_countEngagement
post_typeFormat
keyword, keyword_in_textWhat 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.

EventWhen it is chargedFree planBronze (Starter)Silver (Scale)Gold (Business)
post-scrapedOnce 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-startOnce 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

  1. Open the actor in Apify Console, set your input and click Save as a new task.
  2. In the task, open Schedules, click Add schedule and pick how often (every morning, every Monday at 08:00 and so on).
  3. Use sortBy set to latest and compare runs on post_id to see what is new.
  4. 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"

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

Leads and business directories

Marketing, SEO and reviews

LinkedIn

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.