~ / guides / How to Scrape Facebook: A Python Guide

How to Scrape Facebook: A Python Guide

MR
Marcus Reed
Founder & lead tester · about the author
the short version
  • Plain requests does not work on Facebook. I fetched public pages live in June 2026 and every one returned HTTP 400 with a 1.5 KB error stub, not the page. Output is pasted below.
  • Facebook's robots.txt sets Disallow: / for the default user-agent, bans Scrapy by name, and opens with a notice that automated collection is prohibited without written permission.
  • Meta's Terms of Service section 3.2.2 prohibits collecting data by automated means. Scraping public pages also pulls in personal data, so GDPR applies the moment you store EU residents' info.
  • Because the DIY path is blocked at the door, a scraper API like ChocoData that renders pages and rotates IPs is the realistic route for public Facebook data, with the legal limits unchanged.

Facebook holds the largest store of public social data on the web: business pages, public posts, reviews, follower counts, ad activity. It is also among the hardest targets to scrape, and the difficulty starts before you parse a single tag. I spent June 2026 testing what a plain Python scraper pulls from logged-out Facebook. The short answer: nothing useful. Every public page I requested returned an HTTP 400 error stub, and I have the real output below. This guide shows exactly where the walls are, why the usual requests-and-BeautifulSoup recipe fails here, and what the realistic path looks like for public Facebook data.

Can you legally scrape Facebook?

Scraping public Facebook data is not automatically illegal in the US, but it breaches Meta’s Terms of Service and pulls you straight into data-protection law, so the legal picture has three separate layers. Treat them independently, because winning on one says nothing about the others.

The first layer is computer-crime law. US courts have generally held that scraping data open to the public without a login does not violate the Computer Fraud and Abuse Act, the reasoning the Ninth Circuit used in hiQ Labs v. LinkedIn in 2022. That logic applies to Facebook’s public surfaces too, which is why platforms lean on contract and property claims instead.

The second layer is Meta’s own contract. Meta’s Terms of Service section 3.2.2 (“What you can share and do on our Products”) states you may not “access or collect data from our Products using automated means (without our prior permission).” Facebook’s robots.txt opens with the same message in plainer words: “Collection of data on Facebook through automated means is prohibited unless you have express written permission from Facebook.” Meta enforces this in civil court. In Meta v. Bright Data (N.D. Cal., filed 2023), Meta sued a data vendor over scraping; in January 2024 the court granted Bright Data summary judgment on the public-data claims, a result widely read as confirming that public, logged-out scraping is hard for a platform to block on contract grounds alone. The breach risk is real for logged-in access regardless.

The third layer is data protection, and for Facebook it is the one that bites. Almost everything on Facebook is personal data: names, photos, posts, who liked what. The moment you store information about an EU resident, GDPR applies, and a US scraper has no Facebook-granted basis to process it. California’s CCPA/CPRA reaches residents there. I cover the general framing in my is web scraping legal guide. For Facebook specifically, the defensible posture is narrow: collect only public, non-personal business data (a page’s follower count or category, not the list of individuals who liked a post), never log in a bot account, and get counsel before you store anything tied to identifiable people.

What data is available on a public Facebook page?

Public Facebook pages expose a defined set of business and engagement fields; private profiles, friend lists, and anything behind the login wall are off limits. The table below lists what is publicly visible on a typical business Page, drawn from the field sets that commercial Facebook scrapers advertise (for example Apify’s Facebook Pages Scraper). “Public” here means what the page owner chose to show logged-out visitors; it does not mean a plain HTTP request can fetch it, which is a separate problem covered in the next section.

SurfaceFieldPublic?Notes
Business PageName, username, page IDYesStable identifiers
Business PageCategory, intro/aboutYesOwner-set
Business PageLikes, followers countYesAggregate numbers
Business PageRating, review countUsuallyIf reviews enabled
Business PagePhone, email, address, websiteSometimesOnly if owner published them
Business PageProfile and cover image URLsYesDirect CDN links
Public postPost text, timestamp, post URLYesOn public pages
Public postReaction, comment, share countsYesAggregate numbers
Post reactionsList of individual users who reactedPersonal dataNames and profile URLs of people
User profileAnything beyond name and pictureNoLogin wall, and personal data
Private groups, friend lists, messagesEverythingNoNever public

The line that matters for risk: aggregate page metrics (a follower count, a category) are the low-risk target. Lists of individuals (who liked a post, who commented) are personal data on real people, and that is where the data-protection exposure concentrates. Build around the page-level numbers, not the people.

Can you scrape Facebook with Python requests? (Method 1: DIY)

No. I tested it in June 2026, and plain requests to public Facebook pages returns an HTTP 400 error stub, not the page. This is the result you need to see before you spend a day building selectors that will never run. Here is the exact code I executed:

import requests
import re

UA = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/126.0.0.0 Safari/537.36"
    ),
    "Accept-Language": "en-US,en;q=0.9",
}

for url in [
    "https://www.facebook.com/Meta",
    "https://www.facebook.com/zuck",
    "https://www.facebook.com/",
]:
    r = requests.get(url, headers=UA, timeout=25)
    text = re.sub(r"<[^>]+>", " ", r.text)
    text = re.sub(r"\s+", " ", text).strip()
    print(f"{url} -> {r.status_code}, {len(r.text)} bytes")
    print("   ", text[:120])

The real output, run June 2026 with requests 2.34.2 on Python 3.13.7:

https://www.facebook.com/Meta -> 400, 1542 bytes
    Error Sorry, something went wrong. We're working on getting this fixed as soon as we can. Go back Meta ©
https://www.facebook.com/zuck -> 400, 1542 bytes
    Error Sorry, something went wrong. We're working on getting this fixed as soon as we can. Go back Meta ©
https://www.facebook.com/ -> 400, 1542 bytes
    Error Sorry, something went wrong. We're working on getting this fixed as soon as we can. Go back Meta ©

That 1542-byte body is the entire response: a static “Sorry, something went wrong” page with no Page data, no login form, no JSON, nothing to parse. Facebook does not even bother serving you the login wall from a bare client; it short-circuits to a 400. I also hit facebook.com/photo.php, which returned a 404 with a large body, but that body was just Facebook’s CSS-variable shell and app bootstrap, again with zero content. So there is no BeautifulSoup snippet to give you here, because there is no HTML worth parsing. If you are learning the stack, my requests guide and BeautifulSoup guide use targets that actually return data; Facebook is not one of them.

Two facts compound the block. First, Facebook renders its real interface through heavy client-side JavaScript, so even a 200 would hand you an app shell, not content. A plain HTTP library never executes that JavaScript. Second, the robots.txt disallows everything for the default user-agent and names Scrapy in its blocklist, so the standard crawl frameworks are explicitly unwelcome here. The honest conclusion: the DIY requests path does not work on Facebook, full stop.

Why does Facebook block plain scrapers so hard?

Facebook stacks several defenses, and a plain HTTP request fails the first one before the others even apply. Understanding the layers tells you why a browser engine is the minimum, and why even that is not enough at volume.

LayerWhat it doesWhat it blocks
Edge filteringReturns 400 to bare/unrecognized clientsPlain requests, curl, basic bots
JavaScript renderingContent loads via client-side JSAny non-browser HTTP client
Login wallMost data requires an authenticated sessionLogged-out deep access
Rate limits and checkpointsThrottles and challenges fast or odd trafficHigh-volume scraping, datacenter IPs
Account enforcementBans bot accountsLogged-in automation

The practical reading: my test died at layer one, the edge filter, with a 400. Clear that with a real browser and convincing headers and you meet layer two, JavaScript rendering, which needs a full engine like Playwright. Get content rendering and you meet layer three, the login wall, which gates most non-Page data. Push request volume from one IP and layers four and five (rate limits, checkpoints, account bans) shut you down. Each layer is a separate engineering problem, which is why scraping Facebook yourself is a maintenance project, not a script. My scraping without getting blocked guide covers the headers, fingerprinting, and IP-rotation tactics these layers force on you.

A browser-automation approach with Playwright can clear the first two layers because it executes JavaScript and presents a real browser fingerprint. I did not include a Playwright Facebook script with pasted output here, because doing it properly means driving a logged-out session against pages that still gate most data behind login, and I will not show fabricated results. If you want to see Playwright working end to end on a target that returns data, that belongs in a dedicated browser-scraping guide, not stapled to a target that walls you off.

How do you scrape public Facebook data at scale? (Method 2: scraper API)

Route the request through a scraper API that runs a real browser, rotates residential IPs, and returns the rendered page, then you parse the result. For Facebook this is the realistic option rather than the upgrade option, because the DIY path failed at the first request. A scraper API absorbs the JavaScript rendering, the IP rotation, and the retry-on-block logic that you would otherwise rebuild and maintain yourself.

ChocoData is one such service, with a universal endpoint plus a set of dedicated endpoints. The request shape is a single GET with your target URL and an API key, with JavaScript rendering switched on for a JS-heavy target like Facebook:

import requests

API_KEY = "YOUR_CHOCODATA_KEY"

target = "https://www.facebook.com/Meta"

r = requests.get(
    "https://api.chocodata.com/api/v1/universal",
    params={
        "api_key": API_KEY,
        "url": target,
        "render_js": "true",
    },
    timeout=60,
)

print("STATUS:", r.status_code)
# r.text holds the rendered HTML. Parse the public Page fields
# (name, category, follower count) with BeautifulSoup once you
# confirm the live selectors against the rendered markup.

I did not run this snippet, because it needs a paid key, so treat the parameter names as illustrative and confirm them against ChocoData’s own docs before you build on them. The principle holds across any reputable scraper API: you hand it the URL, it returns the rendered page from a rotating residential IP, and Facebook’s edge filter, JS rendering, and rate limits become the vendor’s problem. ChocoData advertises residential proxy rotation and optional JavaScript rendering, which are the two capabilities Facebook’s defenses make mandatory.

One thing a scraper API leaves untouched: the legal layer. Routing through proxies grants you no permission under Meta’s Terms, and it offers no GDPR cover if you collect personal data. Use this for public, non-personal Page data (counts, categories, public business contact details the owner published), keep individual-level data out of your store, and get counsel before any collection touches identifiable EU or California residents.

Should you build your own Facebook scraper or use a scraper API?

For Facebook, the DIY route is not really on the table, so the practical choice is between a scraper API and not scraping Facebook at all. That is a sharper conclusion than I reach for most targets, and the test results are why. Here is the comparison:

FactorDIY (requests/Playwright)Scraper API
Plain requestsHTTP 400, tested aboveHandled
JavaScript renderingNeeds your own browser engineBuilt in
Login wallYou manage sessions and risk bansVendor handles rendering
IP rotation at volumeYou buy and rotate proxiesBuilt in
Maintenance when Facebook changesYou fix it every timeVendor maintains
Cost”Free” but high engineering timePaid per request
Terms of Service breachYesYes
GDPR exposure on personal dataYesYes

The pattern I would actually follow: skip the DIY attempt for Facebook, because the 400 I documented above means you start at zero and climb a five-layer wall before you see one usable field. If the project genuinely needs public Facebook data, a scraper API is the route that gets you a rendered page without rebuilding Meta’s adversary stack yourself. Then keep the scope tight to public, non-personal business data, because no API removes the Terms breach or the data-protection duty. If the data you need is people-level, the honest recommendation is to reconsider the project.

For the fundamentals under all of this, including headers, rendering, and parsing, see the web scraping guide. The Python scraping guide covers the requests-and-parsing stack on targets that cooperate, and scraping without getting blocked goes deep on the anti-bot tactics that targets like Facebook force you to confront.

FAQ

Is it illegal to scrape Facebook?

Scraping public Facebook data is not automatically a crime in the US, but it breaches Meta's Terms of Service (section 3.2.2 bans automated collection), and Meta has sued scrapers in civil court, including Meta v. Bright Data filed in 2023. Separately, most Facebook data is personal data, so GDPR and similar laws apply when you store information about EU or California residents. Public visibility does not equal permission to collect and republish at scale.

Can I scrape Facebook without logging in?

Not with plain HTTP. In my June 2026 test, logged-out requests to public pages like facebook.com/Meta returned HTTP 400 with a short error stub instead of the page. Facebook serves its real content through heavy JavaScript and gates most of it behind a login wall. A logged-out scraper needs a full browser engine, and even then Facebook throttles and blocks aggressively.

Does Facebook block scrapers?

Yes, at multiple layers. The robots.txt opens by prohibiting automated collection and disallows everything for the default user-agent. Plain requests get a 400. Browser-based scraping hits login walls, rate limits, and checkpoint challenges. Logged-in bot accounts get banned. Facebook is one of the most actively defended scraping targets on the web.

What is the Meta v. Bright Data case about?

Meta sued data provider Bright Data in 2023 over scraping of Facebook and Instagram. In January 2024 a US federal court granted Bright Data summary judgment on the claims tied to scraping public, logged-out data, a result often read as reinforcing that public data scraping is hard for platforms to stop on contract grounds alone. It does not erase the Terms breach for logged-in access or the separate data-protection exposure, so treat it as one data point, not a green light.

MR
Marcus Reed
I've built and run web scrapers for the better part of a decade. On this site I put scraper APIs and scraping tools through real jobs against real targets, then write up what actually holds up.