Alfalfa

How to download all the comments from a Facebook post

Selecting and copying works until about the fortieth comment. After that Facebook is loading them in chunks, replies stay folded away, and your browser's find function cannot see any of it. Here is what actually gets you the whole thread, and why the total you end up with never quite matches the number printed on the post.

Updated September 2026.

Why the manual route fails

A Facebook post does not contain its comments. It contains the first handful and a button that fetches more, and each click fetches another chunk. Replies are a second layer with their own buttons. So the page you can select with a mouse holds a fraction of the conversation, and the fraction changes depending on how long you sat there clicking.

That matters beyond convenience. If you are counting entries, measuring sentiment or quoting people, a partial export is worse than none, because it looks complete.

The number on the post is not the number you can get

This is the single most common surprise, so it is worth settling before you start. A post showing 1,200 comments will not give you 1,200 rows, and nothing is broken when it does not. The headline figure counts several things a public export cannot include:

A realistic expectation: you get every comment and reply that a person browsing without an account would see if they clicked every button, and that is the correct definition of "all" for anything you plan to publish or act on.

The three ways people do this

MethodReality
By handFine to about forty comments. Beyond that you are clicking "view more replies" for an hour and still missing some.
Browser extensionRuns inside your logged-in session. That is the risk: automating actions from your own account is what gets accounts restricted, and the export dies whenever Facebook changes its markup.
Signed-out scraperReads the same public thread with no account attached. Nothing of yours is exposed, and it scales from one post to a thousand.

Doing it

Paste the post URL into the Facebook Comments Scraper, set how many comments you want, and switch on replies if you need the full threads. You get one row per comment:

{
  "commentId": "3000854580150022",
  "date": "2021-08-15T19:58:31.000Z",
  "text": "I'm struck by the goal you \"announced\" to the principal…",
  "profileName": "Aimee J Bednar",
  "profileId": "pfbid0LiAr9wu1KXhDrSfp77CyuFXFVuwgNCsFn7Su…",
  "likesCount": "60",
  "commentsCount": 1,
  "threadingDepth": 0,
  "replyToCommentId": null,
  "commentUrl": "https://www.facebook.com/…?comment_id=3000854580150022"
}

Two fields do the work when you process this. threadingDepth is 0 for a top-level comment and 1 or more for a reply, and replyToCommentId points at the parent, so you can rebuild the thread structure exactly rather than guessing from indentation. One gotcha worth knowing before it bites you: likesCount arrives as a string, because Facebook abbreviates large values. Cast it before you sort on it.

Getting it into Excel

Every run stores its results as a dataset you can download as CSV or Excel from the run's Storage tab. Through the API, append the format you want to the dataset items URL:

curl "https://api.apify.com/v2/datasets/$DATASET_ID/items?format=csv&token=$APIFY_TOKEN" -o comments.csv

Nested fields flatten into columns like author.name. If you only want a few columns, add &fields=date,profileName,text,likesCount and the export comes back narrow enough to read.

Drawing a giveaway winner you can defend

Comment giveaways are the most common reason people need a full export, and they are also where a partial export causes an argument. Three rules make a draw defensible: replies are not entries, one person gets one entry however many times they commented, and the draw must be reproducible by anyone holding the same export.

This does all three. It seeds the random draw from the entry list itself, so re-running it produces the same winner, and anyone you give the export to can verify the result rather than trust you.

import json, random, sys, hashlib

data    = json.load(open(sys.argv[1]))
keyword = sys.argv[2].lower() if len(sys.argv) > 2 else None

entries, seen = [], set()
for c in data:
    if c.get("threadingDepth"):          # 0 = top-level, replies are 1 and deeper
        continue
    if keyword and keyword not in (c.get("text") or "").lower():
        continue
    who = c.get("profileId") or c.get("profileName")
    if not who or who in seen:            # one entry per person, first comment wins
        continue
    seen.add(who)
    entries.append(c)

entries.sort(key=lambda c: c["commentId"])   # stable order, independent of run
seed = hashlib.sha256("".join(c["commentId"] for c in entries).encode()).hexdigest()
random.seed(seed)
winner = random.choice(entries)

print(f"eligible entries : {len(entries)}")
print(f"draw seed        : {seed[:16]}")
print(f"winner           : {winner['profileName']}")
print(f"link             : {winner['commentUrl']}")

Save your export as comments.json and run python3 pick.py comments.json, or add a required hashtag as a second argument: python3 pick.py comments.json "#giveaway". Publish the seed alongside the winner and the draw is auditable.

Other things the export is good for

Before you publish anything from it

Comments are written by identifiable people, which makes them personal data under the GDPR even though anyone can read them. Aggregate analysis is a very different thing from republishing someone's name next to their words, and the second needs more care than the first. Quote sparingly, do not build a profile of an individual out of their comment history, and do not use the author names as a marketing list. None of this is exotic; it is the same standard you would want applied to your own comments.

Questions people ask

Do I need a Facebook account?

No. Comments on a public post are visible to anyone, signed in or not.

Can I get comments from a private group or a personal profile?

No. Anything that requires a login to view is out of scope, deliberately.

Can I run this every day and get only the new comments?

Yes. Schedule the run and de-duplicate on commentId, which is stable.

What does it cost?

$1 per 1,000 comments, no start fee, no surcharge for filtering, with platform usage and residential proxies included. Apify's own comments scraper charges $2.50 per 1,000 on the free plan, plus a fee to start each run, plus an extra fee per comment when a date filter is on.

Try the Facebook Comments Scraper Or scrape the posts themselves