# Facebook Comment Scraper: 25 Posts, 8 Platforms, One Call (https://www.socialcrawl.dev/blog/comment-scraper-api)
> A Facebook comment scraper API that reads up to 25 posts per request across Instagram, TikTok, YouTube, Reddit, X, Threads and LinkedIn. Billed per page.
One `POST /v1/prism/post-comments` call reads the comments under up to 25 post links, and the links can come from Instagram, TikTok, YouTube, Facebook, Reddit, X, Threads and LinkedIn in any mix. Each link gets its own row, in the order you sent them. Add `since` and the call returns only the comments posted after that time, and charges nothing for a post with none.
A mixed call over ten links (two Facebook posts, two Instagram posts, one each from TikTok, YouTube, X, Threads and Reddit, and one link that was not a post) costs 33 credits. The table below breaks that down by platform.
## How do you scrape comments from many posts at once?
Send the post URLs in `items`. `per_post` sets how many comments to read from each post: 20 by default, up to 200. The key goes in the `x-api-key` header.
```bash
curl -X POST "https://www.socialcrawl.dev/v1/prism/post-comments" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"per_post": 20,
"items": [
"https://www.facebook.com/examplepage/posts/pfbid0Example",
"https://www.instagram.com/p/EXAMPLE_CODE/",
"https://www.tiktok.com/@example/video/7000000000000000000",
"https://www.youtube.com/watch?v=EXAMPLE_ID",
"https://x.com/example/status/2000000000000000000",
"https://www.threads.com/@example/post/EXAMPLE_CODE",
"https://www.reddit.com/r/example/comments/abc123/example_thread/",
"https://example.com/not-a-post"
]
}'
```
You do not tell the endpoint which platform a link belongs to. It reads the host, sends the link to that platform's own comment endpoint and puts the result in a row. The response is trimmed here to one Facebook row and the last one.
```json
{
"success": true,
"endpoint": "/v1/prism/post-comments",
"data": {
"results": [
{
"index": 0,
"target": "https://www.facebook.com/examplepage/posts/pfbid0Example",
"status": "ok",
"data": {
"platform": "facebook",
"endpoint": "/v1/facebook/post/comments",
"items": [
{
"comment": {
"id": "Y29tbWVudDo...",
"parent_id": null,
"text": "Holaguay hola",
"author": { "username": null, "display_name": "Example Person" },
"engagement": { "likes": 0, "replies": 0 },
"published_at": "2026-11-11T19:09:02.000Z"
}
}
],
"truncated": true,
"next_cursor": "eyJ...",
"pages": 2
},
"cost": 2
},
{
"index": 7,
"target": "https://example.com/not-a-post",
"status": "unsupported",
"cost": 0
}
],
"summary": { "total": 8, "ok": 7, "unsupported": 1, "credits_charged": 33 }
}
}
```
Inside `data.items`, every platform returns the same `comment` object: `id`, `text`, `author`, `engagement.likes`, `published_at` and `parent_id`. The code that reads a Facebook row reads an Instagram row. Facebook comments carry a `display_name` and do not always carry a `username`, so a script should fall back from one to the other.
`status` is one of `ok`, `not_found`, `unsupported`, `error` or `deferred`. A bad link only fails its own row. A `deferred` row was not started in time, costs nothing, and goes in the next call.
## What does it cost to read comments from 25 posts?
Each post costs what that platform's own comment endpoint charges per page, for the pages that came back with comments. Facebook, TikTok, YouTube, X and Threads are 1 credit a page. Instagram, LinkedIn and Reddit are 5. The call holds the most that `per_post` could read and refunds what the posts did not use.
| Link in the call | Comments read | Credits |
|---|---|---|
| Facebook post | 20 | 2 |
| Instagram post | 20 | 10 |
| TikTok video | 20 | 1 |
| YouTube video | 20 | 1 |
| X post | 20 | 1 |
| Threads post (whole thread) | 8 | 1 |
| Reddit thread (one read) | 5 | 5 |
| A link that is not a post | none | 0 |
A post that cannot be found, a link that is not a post and a post with no comments all cost 0. Facebook and Instagram return about 10 comments a page, which is why 20 comments took two pages. On a list that mixes platforms, Instagram posts make up most of the bill.
The row also tells you when there is more. `truncated: true` with a `next_cursor` means the post has comments beyond `per_post`. Send the cursor to the endpoint named in the row (`data.endpoint`) to continue that post, or raise `per_post`. A Reddit row holds one read of the thread. For the full reply tree of a single thread, use [`GET /v1/reddit/post/comments`](/platforms/reddit/post-comments).
## How do you scrape Facebook comments with Python?
This is the script version of the call above. It reads three posts, writes every comment to a CSV and re-sends any `deferred` row.
```python
API = "https://www.socialcrawl.dev/v1/prism/post-comments"
HEADERS = {"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}
posts = [
"https://www.facebook.com/examplepage/posts/pfbid0Example",
"https://www.tiktok.com/@example/video/7000000000000000000",
"https://x.com/example/status/2000000000000000000",
]
def read_comments(urls, since=None, per_post=50):
body = {"items": urls, "per_post": per_post}
if since:
body["since"] = since
res = requests.post(API, headers=HEADERS, json=body, timeout=120)
res.raise_for_status()
return res.json()
payload = read_comments(posts)
rows = payload["data"]["results"]
# A post that was not started in time comes back "deferred" and costs
# nothing. Send those links again.
deferred = [posts[r["index"]] for r in rows if r["status"] == "deferred"]
if deferred:
rows += read_comments(deferred)["data"]["results"]
with open("comments.csv", "w", newline="", encoding="utf-8") as f:
out = csv.writer(f)
out.writerow(["post_url", "platform", "comment_id", "author", "text", "likes", "published_at"])
for row in rows:
if row["status"] != "ok":
print(row["target"], row["status"])
continue
for item in row["data"]["items"]:
c = item["comment"]
author = c["author"]["username"] or c["author"]["display_name"]
out.writerow([row["target"], row["data"]["platform"], c["id"], author,
c["text"], c["engagement"]["likes"], c["published_at"]])
print("credits:", payload["credits_used"])
```
Swap the three URLs for your own list of up to 25. To collect posts first, search with [`GET /v1/facebook/search/posts`](/platforms/facebook/search-posts) or list a page's posts with `GET /v1/facebook/profile/posts`, then feed the post URLs into this script. The guides to [scraping Facebook](/blog/how-to-scrape-facebook-2026) and [scraping Instagram](/blog/how-to-scrape-instagram-2026) cover that first step.
## How do you get only the new comments?
Add `since`. Each row keeps only comments published at or after that time, and a post with nothing new costs 0.
```bash
curl -X POST "https://www.socialcrawl.dev/v1/prism/post-comments" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"since": "2026-11-13T00:00:00Z",
"per_post": 20,
"items": [
"https://www.instagram.com/p/EXAMPLE_CODE/",
"https://www.youtube.com/watch?v=EXAMPLE_ID",
"https://x.com/example/status/2000000000000000000",
"https://www.facebook.com/examplepage/posts/pfbid0Example"
]
}'
```
When no post has a comment after `since`, every row comes back `ok` with no comments and the call costs 0 credits.
Instagram, YouTube, X and LinkedIn list comments newest first, so the read stops at the first comment older than `since`. TikTok, Facebook, Reddit and Threads do not, so the post is read up to `per_post` comments and then filtered. On a busy post, raise `per_post` or the newest comments may sit beyond what you read. Run the poll on a schedule and pass the time of your last run as `since`. The [Comments in bulk](/docs/recipes/comments-in-bulk) recipe has a TypeScript version of that loop. The launch is in the [changelog](https://www.socialcrawl.dev/changelog#prism-post-comments-2026-10-25).
## How do you read comments on one X, Threads or LinkedIn post?
When you have one link and want to page through it, use `GET /v1/prism/comments`.
```bash
curl "https://www.socialcrawl.dev/v1/prism/comments?url=https://x.com/example/status/2000000000000000000&max=20&replies=false" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"
```
X and Threads cost 1 credit a page and at least 2 a call. LinkedIn costs 5 credits for a page of 10 comments. Threads `/t/` short links work. Replies are not expanded on these three platforms, and the response says so in `_warnings`. On Threads, a short thread comes back whole with `completed: true`. On X, a busy post returns a page and a `next_cursor` to continue from. See the [changelog entry](https://www.socialcrawl.dev/changelog#prism-comments-x-threads-linkedin-2026-11-05) for the platforms added.
## How do you track new comments on a profile?
`GET /v1/prism/profile/comments` reads a profile's recent posts and returns their new comments in one list, newest first. It charges per post, not per call.
```bash
curl "https://www.socialcrawl.dev/v1/prism/profile/comments?url=https://www.instagram.com/example/&posts=3&per_post=10&since=2026-11-01T00:00:00Z" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"
```
For three Instagram posts, the call cost 16 credits without `since`: 1 for the post list and 5 for each post's comment page. With a `since` that only two of the posts had comments after, it cost 11, and `posts[].credits` showed the quiet post at 0. With a `since` later than every comment it cost 1, the post list. Before the per-post billing change, one new comment billed the comment page of every post in the list ([changelog](https://www.socialcrawl.dev/changelog#prism-profile-comments-per-post-billing-2026-10-22)).
## When should a loop become one call?
If you already call a single comment endpoint in a loop, the API tells you. When one key sends 10 or more single calls for different items within a minute, the response carries a `meta.hint` that names the one-call route. For comments, that is `POST /v1/prism/post-comments`. A key gets each hint at most once a day, and the header `X-SocialCrawl-Hints: off` turns hints off.
For more than 25 posts, split the list, or run up to 1,000 comment reads in the background with `POST /v1/prism/jobs` (see [async requests](/docs/async)). Send an `Idempotency-Key` header and a retry of a timed-out call returns the first answer for 0 credits ([idempotency](/docs/idempotency)). All the batch endpoints are listed in [Batch endpoints](/docs/batch).
## What are the limits?
- **Depth differs by platform.** `per_post` goes to 200, but what a post can give depends on the platform and on what is public.
- **Replies are not expanded here.** Replies on X, Threads and LinkedIn stay collapsed. Facebook, Instagram, TikTok and YouTube replies have their own endpoints.
- **A post that cannot be found is free and absent.** It comes back `not_found`, and the other rows are unaffected.
- **`since` is not the same read everywhere.** See the newest-first list above, and raise `per_post` where it applies.
- **A Reddit row is one read of the thread.** It is not the full reply tree.
The YouTube and TikTok versions of this job have their own guides: [YouTube comment scraper](/blog/youtube-comment-scraper) for paging a video to the end, and [scraping TikTok comments in Python](/blog/how-to-scrape-tiktok-comments-python). Once the comments are in a file, [comment sentiment analysis](/blog/comment-sentiment-analysis-api) and [audience questions in comments](/blog/audience-questions-in-comments) cover what to do with them.
## How do you start?
Sign up for a key at [socialcrawl.dev](/docs/quickstart). New accounts get 100 credits and no card is needed. Then run the first curl above with two or three of your own links. The full parameter list is on the [post-comments endpoint page](/platforms/prism/post-comments), and the pricing note for every comment endpoint is on [Facebook](/platforms/facebook/post-comments) and [Instagram](/platforms/instagram/post-comments).
## Frequently asked questions
### How do I scrape Facebook comments?
Send the Facebook post URLs in `items` to `POST /v1/prism/post-comments` with an `x-api-key` header. Each post comes back as a row of comments in a common shape, 1 credit a page, about 10 comments a page. For one post paged to the end, use `GET /v1/facebook/post/comments` and follow `next_cursor`.
### Is there an Instagram comment scraper in the same call?
Yes. Instagram post links go in the same `items` list as Facebook, TikTok, YouTube, Reddit, X, Threads and LinkedIn links. Instagram is billed at 5 credits a page, so 20 comments from one post cost 10 credits.
### How much does it cost to scrape comments from 25 posts?
Each post is billed at its own platform's comment price, per page that came back with comments. TikTok, YouTube, Facebook, X and Threads are 1 credit a page. Instagram, LinkedIn and Reddit are 5. Links that are not posts, posts that cannot be found and posts with no comments cost 0.
### Can I read only the comments posted since my last run?
Yes. Pass `since` as an ISO timestamp. Each row keeps only comments at or after it, and a post with none costs nothing. Instagram, YouTube, X and LinkedIn stop reading at the first older comment. On TikTok, Facebook, Reddit and Threads, raise `per_post` on busy posts.
### Does it return replies?
Replies on X, Threads and LinkedIn are not expanded. Each row holds the comments under the post. Facebook, Instagram, TikTok and YouTube have separate reply endpoints, and a Reddit thread's full reply tree comes from `GET /v1/reddit/post/comments`.
### What if a link is not a post?
That row comes back `unsupported` at 0 credits, and the rest of the call runs normally. The same holds for a post that cannot be found, which returns `not_found`.