Developer Docs

Facebook Scraper: Page Posts & Ads Library

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": [ … ] }: recordLimit caps records per target, and each element in targets uses 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 recordLimit in 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

countries is required (at least one country code) to scope the search; search_terms / ad_type and others are optional filters. The number of ads returned is capped by the top-level recordLimit in 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 with GET /v1/scraper/runs/{id}/records?page=1&pageSize=20, or download the full result with GET /v1/scraper/runs/{id}/download?format=json|csv|excel.
  • Progress & per-target results: poll the run object's targetsOk / targetsFailed for progress; a single page/search failing does not fail the whole run — details are in tasks[].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 credits 402, rate limit 429 + 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