# How to Scrape Facebook in 2026: 5 Methods That Still Work (https://www.socialcrawl.dev/blog/facebook-data-api-2026) > Facebook's Graph API barely covers public data now. 5 working ways to pull page, post, and comment data in 2026, with Python examples and real pricing. In 2026, the Facebook Data API landscape is split between Meta's official Graph API (which requires App Review and carries strict rate limits) and third-party unified APIs that offer immediate programmatic access via a single key. This guide covers both paths in full. Graph API v18.0 expired January 26, 2026. v19.0 expired May 21, 2026. The `metadata=1` parameter (the introspection shortcut developers used to discover available fields on any node) was removed across every Graph API version on May 19, 2026. If you built a Facebook integration before 2025 and haven't touched it since, there's a reasonable chance it's already broken. This guide maps every working path to Facebook data in 2026: what the official Graph API still gives you, what's behind a hard wall, and how to pull page posts, follower counts, and engagement metrics via a single API key with no app review. Examples are in curl and Python. We'll use the SocialCrawl API for the production path and the official Graph API for context on what it still covers. --- ## What Does the Facebook Graph API Actually Give You in 2026? The Graph API is Meta's official programmatic interface to Facebook data, operating over HTTPS at `graph.facebook.com`. It uses a node/edge/field model: nodes are objects (Pages, Posts, Users, Photos), edges are connections between them, and fields are properties on those objects. **Current version:** v25.0, released February 18, 2026. Available versions run from v20.0 through v25.0 ([see Meta changelog](https://developers.facebook.com/docs/graph-api/changelog/)). v18.0 and v19.0 are expired: any code still pointing at those versions returns errors today. **What's accessible with the right permissions:** - Page posts and feed via `/page/feed`, `/page-post`, and `/page-post/comments`, requiring the **Page Public Content Access** feature, which itself requires App Review - Page business metadata: name, category, location, contact details - Reactions, comment counts, and share counts via Page Public Content Access - Ads and Marketing data for ad accounts you own, via the Marketing API - Webhooks for real-time notifications (new comments, reactions on Page posts) **What's officially off-limits:** - Personal user profiles and private content (user data is strictly app-scoped and requires explicit OAuth consent from each user) - Group posts and membership - Friend lists and social graphs between users, closed since 2015 - Audience demographics beyond what the Page itself owns, removed after 2018 - Private messages, available only through the Messenger Platform for page-initiated conversations **The App Review bottleneck** Every Page-related permission requires App Review before a live app can access real data. During development mode, your app can only access Pages where the same person holds both the Page admin role and an app developer or tester role. You cannot test against arbitrary public pages without clearing App Review first. Page Public Content Access specifically requires: 1. Completed App Review 2. Business verification, with possible additional contracts 3. A system user access token (recommended to avoid rate limit collisions on shared tokens) **Rate limits that scale against a user base you don't have yet** The platform rate limit for app tokens is `200 × Number of Daily Active Users` calls per rolling hour. A new app with no users gets zero meaningful headroom. The Pages API rate limit is `4,800 × Number of Engaged Users` per 24-hour window. For a new integration, this math is brutal. The specific throttle error codes to know: `4` (app limit reached), `32` (Pages API limit), `80001` (Pages API with page or system user token). Rate limit usage is exposed via the `X-App-Usage` response header, returning three percentages: `call_count`, `total_cputime`, and `total_time`. **One more live deprecation:** In v25.0, `metadata=1` was deprecated. As of May 19, 2026, it was removed for **all Graph API versions**, not just v25.0. This parameter was a common debugging shortcut for field discovery. It no longer exists. Use the [Graph API Explorer](https://developers.facebook.com/tools/explorer/) or the reference documentation instead. The honest picture: Graph API is the compliant official path if you qualify. But qualification takes weeks, and rate limits scale against a user base most new integrations don't have. For teams that need data now, a third-party unified API is the practical alternative to Facebook Graph API: no App Review, no rate limit math tied to an unknown user base, and immediate x-api-key access from the first request. --- Five methods to scrape Facebook data in 2026, shown as five routes into a walled garden ## How Do You Scrape or Access Facebook Data in 2026? Five Methods Compared Finding a reliable path to Facebook data is harder than it looks. Here are the five methods that actually work in 2026, with honest trade-offs on each. | Method | Entry cost | Data freshness | App Review required? | Multi-platform? | | --------------------- | ------------- | --------------------- | -------------------- | --------------- | | Official Graph API | Free | Real-time | Yes | Facebook only | | Apify Facebook actors | $29/mo | Near real-time | No | Facebook family | | Bright Data datasets | $250 minimum | Batch (pre-collected) | No | No (bulk only) | | RapidAPI scrapers | Not published | Near real-time | No | Single-purpose | | Unified API (one key) | Credit-based | Near real-time | No | 43 platforms | **Official Graph API** is the right path if you qualify. Data freshness is excellent, the authentication model is stable, and Meta is the canonical source. The cost is the weeks-long App Review process and rate limits that start at zero. **Apify** runs browser automation against Facebook's public pages. Their [Facebook Posts Scraper](https://apify.com/apify/facebook-posts-scraper) has 82,000 total users and 8,700 monthly active users. The demand is clearly real. The structural limitation: every time Facebook changes its page layout, selectors break. Budget for ongoing maintenance, not a one-time setup. **Bright Data** offers [10 distinct Facebook dataset types](https://brightdata.com/products/datasets/facebook) with over 1.4 billion records, starting at $0.0025 per record. The key constraint: this is a bulk dataset product, not a per-request API. If you need to query a specific page's current follower count right now, Bright Data is the wrong tool. **RapidAPI** hosts multiple community-maintained Facebook scrapers. Pricing was not published on the marketplace hub page at time of writing; check individual vendor listings before budgeting. **A unified schema** across platforms is the fifth option, covered in the next steps below. One note on the legal angle: the Ninth Circuit's 2022 ruling in _hiQ v. LinkedIn_ held that scraping publicly accessible data likely does not violate the CFAA. Facebook's data is largely login-gated, which distinguishes it from the fully public LinkedIn profiles in _hiQ_, so the legal picture for Facebook specifically is less settled. The lower-risk routes are the official API and unified APIs with published Terms of Service. This is not legal advice. The full picture is in the FAQ below. --- ## Facebook Scraper API Pricing: What 1,000 Page Profiles Actually Cost Pricing across Facebook data tools is poorly documented by design. Here's what the published numbers show: | Tool | Entry price | Cost per 1,000 pages | Minimum spend | Per-request? | | --------------- | -------------- | ----------------------- | ------------- | -------------- | | Apify (Starter) | $29/mo | ~$5–8 all-in | $29/mo | Yes | | Bright Data | $0.0025/record | $2.50 | $250 | No (bulk only) | | RapidAPI | Not published | Not published | Not published | Varies | | SocialCrawl | Credit-based | See [pricing](/pricing) | None | Yes | One note on Apify's numbers: the actor page shows a base rate, but total platform cost (compute included) runs $5–8/1,000 pages all-in per their own FAQ. Budget against the higher figure. Bright Data's $250 minimum makes it impractical for per-request lookups. If you need one page's current data, you're paying $250 for 100,000 records and using one. For bulk collection at scale (sentiment analysis across thousands of brand pages), the per-record math becomes genuinely competitive. For a broader cost breakdown across social platforms, see [our full comparison of social media scraping APIs](/blog/best-social-media-scraping-apis-2026). --- ## Prerequisites Before the first curl command, you need: - **A SocialCrawl API key:** sign up at [socialcrawl.dev](/signup). No App Review, no OAuth negotiation with Meta. Your key is in the dashboard immediately after signup. - **curl** (any version) OR **Python 3.8+** with the `requests` library (`pip install requests`) - **For the Graph API comparison sections:** a Meta developer account with an app in development mode (optional, only needed if you're following the official path) - **No Facebook Business Manager account required** for the unified API path --- ## Step 1: Get a Facebook Page's Followers, Posts, and Engagement The SocialCrawl Facebook page data API follows the same pattern as every endpoint in the series: `GET /v1/{platform}/{resource}` with your key in the `x-api-key` header. For a Facebook page profile: **curl:** ```bash curl "https://www.socialcrawl.dev/v1/facebook/profile?url=https://www.facebook.com/NASA" \ -H "x-api-key: YOUR_API_KEY" ``` **Python:** ```python API_KEY = os.environ["SOCIALCRAWL_API_KEY"] BASE_URL = "https://www.socialcrawl.dev" HEADERS = {"x-api-key": API_KEY} response = requests.get( f"{BASE_URL}/v1/facebook/profile", headers=HEADERS, params={"url": "https://www.facebook.com/NASA"} ) page = response.json() data = page["data"] print(f"Page: {data['name']}") print(f"Category: {data['category']}") print(f"Followers: {data['followers_count']:,}") print(f"Likes: {data['likes_count']:,}") # engagement_rate is computed, not a raw field the Graph API returns print(f"Engagement rate: {data['engagement_rate']}%") # content_category classifies the page's content type from post history print(f"Content category: {data['content_category']}") ``` Two fields worth noting explicitly: - `engagement_rate` is computed from raw counts: the Graph API returns individual like, comment, and share counts and leaves the rate calculation to you. It's pre-calculated in this response. - `content_category` is a broader content-type classification computed from the page's post history. The Graph API has a `category` field for business type (e.g., "Science Website"), but this is different: it classifies what the page actually publishes. The `x-api-key` header replaces the Graph API's OAuth flow entirely. No token expiry to manage, no scope negotiation, no refresh dance. --- ## Step 2: Pull Posts and Comments at Scale with Cursor Pagination Fetching one page profile is a warmup. The real pattern for extracting Facebook data at scale is pulling hundreds of posts, for content monitoring, competitor analysis, or sentiment tracking. The API uses cursor-based pagination: each response includes a `next_cursor` value you pass back on the next request. ```python API_KEY = os.environ["SOCIALCRAWL_API_KEY"] BASE_URL = "https://www.socialcrawl.dev" HEADERS = {"x-api-key": API_KEY} def fetch_all_posts(page_username: str, max_pages: int = 10) -> list[dict]: """Fetch posts from a Facebook page using cursor pagination.""" all_posts = [] cursor = None page_num = 0 while page_num < max_pages: params = {"url": f"https://www.facebook.com/{page_username}", "limit": 25} if cursor: # Pass the cursor from the previous response to get the next page params["cursor"] = cursor response = requests.get( f"{BASE_URL}/v1/facebook/profile/posts", headers=HEADERS, params=params ) result = response.json() posts = result.get("data", {}).get("items", []) all_posts.extend(posts) # next_cursor is None when you've reached the end of available data cursor = result.get("data", {}).get("next_cursor") if not cursor: break page_num += 1 # Rate-conscious pause between pages: keeps the pattern from # looking like a burst. Actual retry logic is in Step 3. time.sleep(0.5) return all_posts posts = fetch_all_posts("nasa", max_pages=5) print(f"Fetched {len(posts)} posts") ``` The `limit` parameter controls items per page; 25 is a reasonable default. The `cursor` parameter accepts the `next_cursor` value from the previous response. When `next_cursor` is `None` or absent, you've reached the end of available data. The `time.sleep(0.5)` is not rate limit handling; it's a basic courtesy pause between cursor pages. Full exponential backoff lives in Step 3. --- Handling Facebook API rate limits with pacing and backoff so the data pipeline never breaks ## Step 3: How Do You Handle Rate Limits Without Breaking Your Pipeline? Graph API throttle errors arrive as specific error codes: `4` (app limit), `32` (Pages API limit), `80001` (Pages API with page or system user token). The `X-App-Usage` response header shows you `call_count`, `total_cputime`, and `total_time` as percentages; preemptive throttling when any of those approaches 100% is smarter than reactive backoff after an error. For the credit-based path: credit deduction is transparent per request in the response envelope. No opaque sliding window math: check your credit balance before a large pull, not after. This pattern handles both: retries on `429` with exponential backoff, logs `X-App-Usage` for Graph API monitoring, and hard-stops on client errors rather than retrying indefinitely: ```python API_KEY = os.environ["SOCIALCRAWL_API_KEY"] BASE_URL = "https://www.socialcrawl.dev" HEADERS = {"x-api-key": API_KEY} def fetch_with_retry( url: str, params: dict, max_retries: int = 5 ) -> dict | None: """Fetch with exponential backoff on rate limits.""" for attempt in range(max_retries): response = requests.get(url, headers=HEADERS, params=params) # Log X-App-Usage when present: Graph API pass-through header usage = response.headers.get("X-App-Usage") if usage: print(f"Graph API usage: {usage}") if response.status_code == 200: return response.json() if response.status_code == 429: # Jitter prevents thundering herd when multiple workers # hit the limit at exactly the same moment wait = (2 ** attempt) + random.uniform(0, 1) print(f"Rate limited. Waiting {wait:.1f}s (attempt {attempt + 1}/{max_retries})") time.sleep(wait) continue # 4xx other than 429 are caller errors, don't retry if 400 <= response.status_code < 500: print(f"Client error {response.status_code}: {response.text[:200]}") return None # 5xx: transient server error, retry with backoff wait = (2 ** attempt) + random.uniform(0, 1) print(f"Server error {response.status_code}. Waiting {wait:.1f}s") time.sleep(wait) print(f"Exhausted {max_retries} retries") return None ``` The key distinction: `429` is a rate limit, so back off and retry. A Graph API error code `80001` means the Pages API throttle was hit with a page or system user token; the same exponential backoff applies. Any `4xx` other than `429` is a caller error (wrong endpoint, missing field, expired version) and should not be retried automatically. --- ## What Could Go Wrong? These are the specific failure modes, each with a one-line diagnosis. **Empty `data` array returned** For Graph API: Page Public Content Access is not yet approved. Check your app's Feature Review status in the Meta developer dashboard. For the unified API path: verify the endpoint matches the resource type you're targeting (page vs. posts vs. comments). **401 / invalid token** For the `x-api-key` path: your key is missing from the header or was regenerated in the dashboard. Copy the current key and retry. For Graph API: your access token expired. Graph API tokens from the three-legged OAuth flow have finite lifespans and require proactive renewal. **Requests failing silently after May 19, 2026** You were relying on `metadata=1` for field discovery. It was removed across every Graph API version on that date. Switch to the [Graph API Explorer](https://developers.facebook.com/tools/explorer/) or the field reference for discovery. **400 errors on v18 or v19 endpoint calls** Both versions expired in 2026 (v18.0 on January 26, v19.0 on May 21). Update your base URL to v22.0 or higher. v25.0 is current as of February 2026. **Rate limit error code 80001** Pages API throttle on a page or system user token. Implement exponential backoff: the pattern in Step 3 handles this. If you're hitting it repeatedly, add `X-App-Usage` logging to catch the approach before the wall. --- ## What's Next? Extend to Instagram, LinkedIn, and Beyond If you're querying Facebook pages, you're probably querying Instagram too. The [Instagram data guide](/blog/instagram-scraping-2026) covers the same pattern (Reels, Stories, and profile data) under the same key. No separate app review per platform. The [unified social media API complete guide](/blog/best-social-media-scraping-apis-2026) covers the architecture decision in full: when a unified layer makes sense over platform-specific integrations, and how schema normalization works across 43 platforms under one API key. For the rest of the series: the [LinkedIn Data API guide](/blog/linkedin-data-api-2026) covers the restricted official API and what's available via third-party paths; the [X/Twitter API guide](/blog/x-twitter-api-2026) covers the tiered pricing shift and what each tier actually returns; the [YouTube Data API guide](/blog/youtube-data-api-2026) covers quota math and the endpoints that cost the most; and the [Reddit Data API guide](/blog/reddit-data-api-2026) covers programmatic access to posts, comments, and subreddit data after the 2023 API access changes. The visual explorer lets you see a Facebook page's full response before you write a single line of code. [The Explorer](/explorer) is the fastest way to confirm which fields are available for your use case. --- {/* FAQ START */} ## Frequently Asked Questions ### What data can I get from the Facebook Data API? Via the official Graph API with Page Public Content Access approved: public page posts, comments, reactions (with breakdown by type: like, love, haha, wow, care), follower count, page category, engagement metrics, media URLs, and post timestamps. Officially off-limits: personal user profiles, group content, friend graphs (closed since 2015), and audience demographics beyond what the page owns (removed after 2018). Via a unified social data API: page profile data including follower count, category, and post history; individual posts with engagement counts; and comment threads. Computed fields (`engagement_rate` and `content_category`) are pre-calculated in the response rather than left as raw counts to aggregate yourself. ### How do I get a Facebook Data API key? **Official Graph API path:** Create a Meta developer account → create an app at developers.facebook.com → request Page Public Content Access → complete App Review → complete Business Verification → generate a system user access token. This process typically takes several weeks. Apps in development mode can only access Pages where the same person holds both the Page admin role and a developer or tester role on the app. **Alternative path:** Sign up at [socialcrawl.dev](/signup) → your API key appears in the dashboard immediately. No App Review, no Business Verification, no OAuth dance. Pass the key in the `x-api-key` header. That's the entire authentication model. ### Is scraping Facebook data legal? The Ninth Circuit's 2022 ruling in _hiQ v. LinkedIn_ held that scraping publicly accessible data likely does not violate the Computer Fraud and Abuse Act. However, most Facebook data sits behind a login wall, which distinguishes it from the fully public LinkedIn profiles at issue in _hiQ_ and leaves the legal picture for Facebook specifically less settled. [Meta's Platform Terms](https://developers.facebook.com/terms/) require App Review and explicitly prohibit unauthorized automated data collection. GDPR applies to any collection of data from EU users regardless of technical method. The lower-risk routes are the official Graph API (if you qualify) and unified APIs with published Terms of Service. **This is not legal advice.** Consult qualified counsel for your specific situation. ### Why does Facebook API return empty data? Four common causes, each with a one-line diagnosis: 1. **Insufficient permissions:** Page Public Content Access not yet approved. Check your app's Feature Review status in the Meta developer dashboard. 2. **Deprecated version:** v18.0 and v19.0 calls return `400` errors. Update your base URL to v22.0 or higher. 3. **Rate limit hit:** check the `X-App-Usage` header. If `call_count` is at or near 100%, you're throttled. Wait for the rolling window to reset and implement backoff (see Step 3). 4. **Field access tier:** some fields require a higher-tier app review than what you've completed. Check the specific permission requirements in Meta's Features Reference. ### What's the best Facebook scraper API in 2026? It depends on the use case: - **Apify** ($29/mo Starter, ~$5–8/1,000 pages all-in) suits one-off Facebook jobs or developer exploration, with solid community coverage, browser automation, and no minimum order. - **Bright Data** ($0.0025/record, $250 minimum) works for bulk pre-collected datasets at scale: sentiment analysis across thousands of pages, academic research, large-scale brand monitoring. Not a per-request API. - **A unified social data API** is the right fit when you need Facebook alongside Instagram, LinkedIn, X, or YouTube under one key: consistent schema, credit-based pricing, no minimum order, no separate auth per platform. Match the tool to the use case. There's no single best answer across all scenarios. ### How do I handle Facebook API rate limits in production? **For the official Graph API:** Monitor the `X-App-Usage` response header before you hit the wall: `call_count`, `total_cputime`, and `total_time` are returned as percentages. When any approaches 100%, pause proactively. Implement exponential backoff with jitter on error codes `4`, `32`, and `80001`. For Pages API at scale, a system user access token is recommended over a standard page access token. **For the credit-based path:** Credit deduction is transparent per request in the response envelope. Check your credit balance before a large pull. The Step 3 pattern above handles `429` responses with exponential backoff if you encounter a temporary rate limit on the upstream fetch. {/* FAQ END */}