---
title: "Facebook Profile Posts API"
method: GET
path: "/v1/facebook/profile-posts"
tags: ["Facebook"]
---

# Facebook Profile Posts API

`GET /v1/facebook/profile-posts`

## Request

- Base URL: `https://api.captapi.com`
- URL: `https://api.captapi.com/v1/facebook/profile-posts`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Latest posts and Reels from a Facebook page — listingHits / timings.phase; 60s deadline, failures 0 credits.

Pass a Facebook page URL or @handle and get that page's recent posts as clean JSON (text posts and Reels mixed). author.username uses one consistent vanity casing across the page (no nasa vs NASA split). engagement always includes views and shares (null when unknown / not a video) — never invents shares:0 from listing noise. The envelope names the yield: requested, totalReturned, listingHits, hydrateFailures, hydrateSkipped, hasMore, truncatedReason=listing-window | hydrate-budget | deadline | null (always keyed), timings{listingMs,hydrateMs,phase,totalMs}, and fetchedAt (not a second scrapedAt). When hasMore is false: listingHits − hydrateFailures − hydrateSkipped = totalReturned. When hasMore is true: min(listingHits, requested) − hydrateFailures − hydrateSkipped = totalReturned. Listing starts with a 1s-wait first-paint hop (~10–16s) so shop-heavy pages (nike) are not spent on a 40s scrolled miss; the scrolled hop and a light /posts tab still run when that paint is empty. Each permalink hydrate is typically 6–10s (can be ~100ms when listing already carried the post) and is capped at 12s. Hydration is sequential and clock-aware: keep going while elapsed + 12s < 60s (the cap, not the typical 6–10s), then return what fits with truncatedReason=hydrate-budget. If the 60s deadline fires after posts have already finished, those posts ship as a 200 with truncatedReason=deadline instead of a 503 with nothing. limit default 4 / max 4 (422 above that); the cap is the ceiling, not a promise. A 503 carries the same timings so phase=listing vs phase=hydrate is readable; phase=listing forces hydrateMs=0. Hard 60s deadline: hang with no posts is 503 unless a 6h last-good page exists (stale 200, 0 credits). Empty live page is 502. Failures are 0 credits. A failed page with no last-good is remembered for 60s so retries are an instant 502/503 with the same timings. Flat 2 credits on the native path.

Docs: https://captapi.com/apis/facebook-profile-posts

## Query parameters

- `url` string, required
- `limit` integer
- `cache` boolean

## Response `200`

Success. The data object for this endpoint.

- object
  - `success` unknown, required
  - `data` object, required
    - `url` string: Facebook page URL you queried.
    - `requested` integer: The limit you sent (default 4, max 4) — a cap, not a promise. The listing hop is ~23–29s typical, hard-capped at 40s; each hydrate is typically 6–10s; the logged-out window often holds 1–3 posts.
    - `totalReturned` integer: Posts in this response (length of posts[]).
    - `listingHits` integer: Distinct candidate posts in this listing HTML window (deduped by post id, not raw hrefs).
    - `hydrateFailures` integer: Listing URLs we tried to hydrate that did not become a post row.
    - `hydrateSkipped` integer: Listing permalinks we found but did not hydrate because the next item would miss the 60s deadline. When hasMore is false: listingHits − hydrateFailures − hydrateSkipped = totalReturned. When hasMore is true: min(listingHits, requested) − hydrateFailures − hydrateSkipped = totalReturned.
    - `hasMore` boolean: true only when listingHits > limit. There is no cursor, and limit cannot exceed 4. hydrateSkipped is not hasMore.
    - `posts` object[]
      - `platform` string: Platform identifier for this response (matches the endpoint's platform).
      - `url` string: Facebook page URL you queried.
      - `id` string: Id of this posts item.
      - `caption` string: Post or creative caption when the platform exposes one.
      - `description` string: Description of this posts item.
      - `publishedAt` string: Publish date (ISO 8601) when the platform exposes an absolute timestamp.
      - `author` object: Author name or handle.
        - `id` string: Id of this posts item.
        - `username` string
        - `displayName` string
        - `url` string: Facebook page URL you queried.
      - `engagement` object: Engagement metrics for the item.
        - `likes` integer
        - `comments` integer
        - `likesIsApproximate` boolean
        - `commentsIsApproximate` boolean
        - `sharesIsApproximate` unknown
        - `views` unknown
        - `shares` unknown
      - `isVideo` boolean: Whether the item is a video.
      - `feedbackId` string: Facebook feedback id for the post (useful for comments threading).
    - `truncatedReason` string, nullable: Always keyed. "hydrate-budget" when we stopped hydrating so the 60s deadline would not become a 503. "deadline" when the 60s ceiling fired after posts had already finished — those posts ship. "listing-window" when the window is exhausted below the limit with nothing skipped. null when nothing truncated.

## Other responses

- `400`: Bad request: wrong platform URL, unknown endpoint, or an invalid parameter value. Not billed.
- `401`: Missing, invalid or revoked API key. Not billed.
- `402`: Not enough credits for this request. Not billed.
- `404`: The resource does not exist or is not public. Not billed.
- `422`: A required parameter is missing or has the wrong type. Not billed.
- `429`: Rate limit reached. Wait for Retry-After seconds. Not billed.
- `502`: The platform could not be reached or returned nothing usable. Retryable, not billed. 503 and 504 use the same envelope.

## Changes

- **2026-10-19** `c9b9ac5ff1bd`: 2 breaking, 7 warning, 11 info
  - the `data/posts/items/engagement/shares` response's property type changed from `integer, null` to no type for status `200`
  - the `data/posts/items/engagement/views` response's property type changed from `integer, null` to no type for status `200`
  - removed the optional property `data/posts/items/author/profileImage` from the response with the `200` status
  - removed the optional property `data/posts/items/author/verified` from the response with the `200` status
  - …16 more

[Operation history](https://skmtc.dev/captapi/apis/captapi-api/changes/v1/facebook/profile-posts/get.md)

---

[API](https://skmtc.dev/captapi/apis/captapi-api.md) · [All operations](https://skmtc.dev/captapi/apis/captapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/captapi/apis/captapi-api/revisions/c9b9ac5ff1bd?raw)
