Scraping is asynchronous: submit a run → poll status → fetch data. See the end-to-end flow in Quick Start; the shared response envelope, run state machine, billing, and error codes are in Auth & Error Handling. This page only lists each Facebook endpoint's submit path, target fields, and output fields.
Endpoint Overview
| Endpoint | Path | Description | One target = |
|---|---|---|---|
| Page Posts | POST /v1/scraper/facebook/page-posts |
Scrape posts, engagement, attachments, and comments from pages | one set of pages |
| Ads Library | POST /v1/scraper/facebook/ads-library |
Search ads served in the Facebook Ads Library | one search |
Common headers:
Authorization: Bearer ants_xxxxxxxxxxxx
Content-Type: application/json
The submit body is always
{ "deliveryMode": "async", "recordLimit": 1000, "targets": [ … ] }:recordLimitcaps records per target, and each element intargetsuses the fields listed per endpoint below.
💡 You can also use
deliveryMode: "sync"(small jobs block until terminal, auto fallback to polling on timeout) — see quick-start · Sync mode.
Page Posts
Scrape posts from one or more Facebook pages, including body text, timestamp, engagement, attachments, and comments.
Endpoint: POST /v1/scraper/facebook/page-posts
Target fields (each element of targets[]):
| Field | Type | Required | Description |
|---|---|---|---|
pageUrls |
string | either/or | Page URL list (JSON array string, e.g. ["https://facebook.com/nike"]; provide pageUrls or pageIds) |
pageIds |
string | either/or | Page ID list (JSON array string, e.g. ["123456789012345"]; provide pageUrls or pageIds) |
resultsLimit |
number | — | Max posts per page (default 50, max 500) |
max_pages |
number | — | Max pages (maps to resultsLimit) |
since |
string | — | Start date (YYYY-MM-DD / ISO); only posts after this date |
until |
string | — | End date; only posts before this date |
includeComments |
boolean | — | Return comments with each post; defaults to false |
commentsLimit |
number | — | Max comments per post (applies when includeComments=true; defaults to 10) |
The posts-per-page cap can also be controlled by the top-level
recordLimitin the submit body (see Quick Start).
Output fields (each record in records):
| Field | Type | Description |
|---|---|---|
postId |
string | Post ID |
permalinkUrl |
string | Post permalink |
message |
string | Post body text |
createdTime |
string | Publish time |
page |
object | Page info |
page.pageId |
string | Page ID |
page.name |
string | Page name |
page.category |
string | Page category |
engagement |
object | Engagement data |
engagement.reactions |
object | Reaction breakdown |
engagement.reactions.like |
number | Like count |
engagement.reactions.love |
number | Love reaction count |
engagement.reactions.wow |
number | Wow reaction count |
engagement.reactions.haha |
number | Haha reaction count |
engagement.reactions.sad |
number | Sad reaction count |
engagement.reactions.angry |
number | Angry reaction count |
engagement.reactions.care |
number | Care reaction count |
engagement.reactions.total |
number | Total reaction count |
engagement.commentsCount |
number | Comment count |
engagement.sharesCount |
number | Share count |
attachments |
array | Attachments |
attachments.type |
string | photo / video / link / album |
attachments.url |
string | Media URL |
attachments.title |
string | Link title (for link type) |
attachments.description |
string | Link description |
attachments.targetUrl |
string | Target URL the attachment points to |
comments |
array | Comments (when includeComments=true) |
comments.commentId |
string | Comment ID |
comments.message |
string | Comment content |
comments.createdTime |
string | Comment time |
comments.from |
object | Comment author |
comments.from.name |
string | Comment author name |
comments.from.id |
string | Comment author ID |
comments.likeCount |
number | Comment like count |
comments.replyCount |
number | Comment reply count |
Submit example:
curl -X POST "https://api.antsdata.com/v1/scraper/facebook/page-posts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"deliveryMode": "async",
"recordLimit": 1000,
"targets": [
{ "pageUrls": "[\"https://facebook.com/nike\"]", "since": "2026-01-01", "includeComments": true, "commentsLimit": 20 },
{ "pageIds": "[\"15087023444\"]" }
]
}'
A successful submit returns HTTP 201 + the run id, with status set to queued:
{ "code": 0, "message": "ok", "data": { "id": 1287346, "status": "queued" } }
Then poll GET /v1/scraper/runs/{id} by id until succeeded, and fetch records or download — see the full poll/fetch flow in Quick Start.
Ads Library
Search ads currently or previously served in the Facebook Ads Library, filtered by keyword, country/region, type, and more. One target = one search.
Endpoint: POST /v1/scraper/facebook/ads-library
Target fields (each element of targets[] = one search):
| Field | Type | Required | Description |
|---|---|---|---|
countries |
array | ✅ Required | Country code list (e.g. ["US"]) |
search_terms |
array | — | Search keywords |
ad_type |
string | — | Ad type filter: ALL / POLITICAL_AND_ISSUE_ADS / HOUSING_ADS |
active_status |
string | — | Delivery status filter: active / inactive / all |
media_type |
string | — | Media type filter: all / image / video / none |
start_date |
string | — | Start delivery date YYYY-MM-DD |
end_date |
string | — | End delivery date YYYY-MM-DD |
countriesis required (at least one country code) to scope the search;search_terms/ad_typeand others are optional filters. The number of ads returned is capped by the top-levelrecordLimitin the submit body.
Output fields (each record in records):
| Field | Type | Description |
|---|---|---|
adArchiveId |
string | Ad archive ID |
snapshotUrl |
string | Ad snapshot page URL |
creationTime |
string | Ad creation time |
startDate |
string | Delivery start date |
endDate |
string | Delivery end date |
advertiser |
object | Advertiser |
advertiser.pageId |
string | Page ID |
advertiser.pageName |
string | Page name |
advertiser.pageUrl |
string | Page URL |
body |
string | Ad body copy |
ctaText |
string | CTA button text |
linkUrl |
string | Landing page URL |
platforms |
array | Delivery platforms (e.g. facebook / instagram) |
creative |
object | Creative |
creative.type |
string | image / video / carousel |
creative.images |
array | Image assets |
creative.images.url |
string | Image URL |
creative.images.caption |
string | Image caption |
creative.videos |
array | Video assets |
creative.videos.url |
string | Video URL |
creative.videos.thumbnailUrl |
string | Video thumbnail |
creative.videos.duration |
string | Duration (seconds) |
creative.carouselItems |
array | Carousel items |
creative.carouselItems.title |
string | Title |
creative.carouselItems.description |
string | Description |
creative.carouselItems.imageUrl |
string | Image URL |
creative.carouselItems.linkUrl |
string | Target URL |
spend |
object | Estimated spend range |
spend.lowerBound |
number | Lower bound of spend (USD) |
spend.upperBound |
number | Upper bound of spend (USD) |
impressions |
object | Estimated impression range |
impressions.lowerBound |
number | Lower bound of impressions |
impressions.upperBound |
number | Upper bound of impressions |
Submit example:
curl -X POST "https://api.antsdata.com/v1/scraper/facebook/ads-library" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"deliveryMode": "async",
"recordLimit": 1000,
"targets": [
{
"countries": ["US", "GB"],
"search_terms": ["nike"],
"ad_type": "ALL",
"active_status": "active",
"start_date": "2026-05-01",
"end_date": "2026-06-30"
}
]
}'
A successful submit returns HTTP 201 + the run id, with status set to queued:
{ "code": 0, "message": "ok", "data": { "id": 1287347, "status": "queued" } }
Then poll GET /v1/scraper/runs/{id} by id until succeeded, and fetch records or download — see Quick Start.
Fetching Data & Errors
- Fetch: once the run reaches
succeeded, page through records withGET /v1/scraper/runs/{id}/records?page=1&pageSize=20, or download the full result withGET /v1/scraper/runs/{id}/download?format=json|csv|excel. - Progress & per-target results: poll the run object's
targetsOk/targetsFailedfor progress; a single page/search failing does not fail the whole run — details are intasks[].errorMessage. - Billing: settled by the number of successfully produced records; if every target fails, the hold is released and nothing is charged.
- Errors: request-level errors return the matching HTTP status code +
{ "code": <int>, "message": <msg> }(e.g. insufficient credits402, rate limit429+Retry-After).
For the envelope, state machine, billing, and full error-code table, see Auth & Error Handling.
FAQ
Q: Can I scrape multiple pages at once?
Yes. targets is an array — a single run can hold multiple searches, and a single target's pageUrls / pageIds can itself carry multiple pages. Per-target status is in the run object's tasks[].
Q: Why don't I get the posts/ads data straight back after submitting?
Scraping is asynchronous: submit to get a run id, it runs in the background, then poll id until succeeded and fetch records or download by id.
Q: Which fields are required for an Ads Library search?
countries is required (at least one country code) to scope the search; search_terms / ad_type and others are optional filters.
Q: Am I charged for failed scrapes?
No. If every target fails, the hold is released and nothing is charged; partial success is billed only for the records actually produced. See Auth & Error Handling.
Next Steps
- Platform guides: TikTok · X · Instagram · LinkedIn · Google · YouTube · Amazon
- Synchronous search: Google SERP
- Auth & Error Handling — Unified envelope, run state machine, billing & error codes
