Skip to main content

facebook-page-info-scraper

Public Facebook page info as a Python dict — fast, no login, no API key.

PyPI Python License Downloads Monthly Weekly

Requests Playwright Scrapy Selenium


⚡ Quick start

pip install facebook-page-info-scraper
from facebook_page_info_scraper import scrape_page

scrape_page("https://www.facebook.com/examplepage")

That is everything — both engines install and are ready to use.


🚀 Two engines, one result

Pick whichever suits the job. Both take the same URLs, return the same fields, and run the same extraction. They differ only in how the page is requested.

🌐 HTTP🎭 Browser
requests withrequestsChromium via Playwright
speed~1.4 s per page~3 s per page
memorynegligible~60–80 MB per page
runs JavaScript
reads network traffic✅ captures GraphQL responses
suitslarge lists, minimal setuppages whose data never reaches the raw HTML
from facebook_page_info_scraper import scrape_pages       # 🌐 HTTP
from facebook_page_info_scraper.spider import run         # 🎭 Browser

scrape_pages(urls, threads=16)
run(urls, threads=8)

The browser engine downloads Chromium (~150 MB) the first time it runs — pip cannot fetch browser binaries, so it happens on first use. One time only.


📖 What it does

Give it a Facebook page URL, get back the page's public details: name, category, email, phone, website, address, likes, ratings, opening status.

🎯 What it solves

Facebook page data used to require driving a real browser — slow, heavy, and it broke every time Facebook changed its CSS. Both engines here read Facebook's own page payload instead, so neither depends on how the page looks.


🌐 Usage — HTTP

from facebook_page_info_scraper import scrape_page, scrape_pages

page  = scrape_page("https://www.facebook.com/examplepage")
pages = scrape_pages(urls, threads=16)

print(page["email"])        # hello@example.com
print(page["page_likes"])   # 12,480
python scrape.py urls.txt                  # -> pages.json
python scrape.py urls.txt --threads 24
python scrape.py urls.txt --out output.json
scrape_page(url,   want_about=True, timeout=25)
scrape_pages(urls, threads=16, want_about=True, timeout=25)

want_about=False reads only the page header — faster, but no email or phone.


🎭 Usage — Browser

from facebook_page_info_scraper.spider import run

run(urls, threads=8)                    # -> pages_browser.jsonl
run(urls, threads=8, headless=False)    # watch it work
python -m facebook_page_info_scraper.spider urls.txt --threads 8
python -m facebook_page_info_scraper.spider urls.txt --headed
python -m facebook_page_info_scraper.spider https://www.facebook.com/examplepage
run(urls,
    threads=8,                  # pages rendered at once, no cap
    out="pages_browser.jsonl",
    settle_ms=2000,             # pause after load before reading
    headless=True)

This engine works in batches — pass a list of URLs rather than one at a time.


📥 Input

Any Facebook page URL. These all work with either engine:

https://www.facebook.com/examplepage
https://facebook.com/examplepage                        (no www)
https://www.facebook.com/examplepage/                   (trailing slash)
https://www.facebook.com/pages/Example-Page/100000000000000
https://www.facebook.com/profile.php?id=100000000000000
http://sv-se.facebook.com/pages/Example-Page/100000000000000   (locale subdomain)

📤 Output

Identical from either engine.

{
  "page_name": "Example Store",
  "page_id": "100000000000000",
  "page_category": "Bakery",
  "email": "hello@example.com",
  "phone_number": "+33 1 23 45 67 89",
  "page_website": "https://example.com",
  "address": "1 Example Street\n12345 Sampletown",
  "page_likes": "12,480",
  "talking_about": "215",
  "were_here": "33",
  "recommend_percent": "94",
  "page_review_number": "18",
  "open_status": "Closed now",
  "price_range": "Price Range - $",
  "bio": "Example Store. 12,480 likes ...",
  "image": "https://scontent.xx.fbcdn.net/...",
  "canonical": "https://www.facebook.com/examplepage",
  "locale": "en_US",
  "ok": True
}

Fields

field type description
page_name str Page name
page_id str Numeric Facebook page ID
page_category str | None e.g. Bakery, Clothing Store
email str | list | None Contact email(s)
phone_number str | list | None Contact phone(s)
page_website str | list | None External website(s)
address str | None Full street address
page_likes str | None Like count, e.g. 12,480
page_followers str | None Follower count
talking_about str | None "talking about this" count
were_here str | None Check-in count
recommend_percent str | None e.g. 74 from "74% recommend"
page_rate str | None Star rating, where shown
page_review_number str | None Review count
open_status str | None Closed now, Always open, …
price_range str | None e.g. Price Range · $
bio str | None Page description
image str | None Profile picture URL
canonical str Canonical page URL
locale str Language Facebook served
ok bool Whether the scrape succeeded
error str Present only when ok is False

Always check ok:

page = scrape_page(url)
print(page.get("page_name")if page.get("ok") else page.get("error"))

One thing to know. email, phone_number and page_website are a string when the page lists one, and a list when it lists several.

"email": "hello@example.com"                          # one
"email": ["sales@example.com", "press@example.com"]   # several
"email": None                                         # none

def as_list(v):
    return [] if v is None else (v if isinstance(v, list) else [v])

🩺 Check your run

One call tells you how a batch went. Works on records from either engine.

from facebook_page_info_scraper import scrape_pages, summarise

records = scrape_pages(urls, threads=16)
summarise(records)
{
  "total": 213,          # records in
  "ok": 211,             # scraped successfully
  "failed": 2,
  "with_about": 164,     # found the About panel
  "with_email": 150,
  "with_phone": 115,
  "with_website": 161,
  "wrong_locale": 0,     # pages Facebook served in another language
  "avg_seconds": 1.44,
  "avg_kb": 533          # bytes actually read, not page size
}

Field counts are measured against ok, not total — dead URLs never drag your extraction numbers down. That makes the two problems easy to tell apart:

what moved what it means
ok dropped fetching — blocks, rate limits, bad URLs
ok steady, with_email dropped extraction — Facebook changed something
wrong_locale above 0 those pages came back in another language

Handy as a guard in scheduled jobs:

stats = summarise(records)
if stats["with_email"] / stats["ok"] < 0.60:
    raise SystemExit("email extraction dropped — check for changes")

📊 Speed

Measured on the same 183-page list, same machine.

🐌 old (Selenium) 🌐 HTTP 🎭 Browser
per page 15–20 s ~1.4 s ~3 s
pages in parallel ✅ 16+ ✅ you choose
200 pages ~50 min under 1 min ~2 min
memory ~60 MB/page negligible ~60–80 MB/page
needs Chrome installed downloads its own

Both engines beat the old Selenium version by a wide margin — HTTP by roughly 50×, the browser engine by about while still running JavaScript.


🔮 Roadmap

An AI extraction layer is planned for the tail that deterministic rules cannot reach — unlabelled free-text rows in languages whose formatting conventions vary, plus self-healing selectors that repair themselves when Facebook changes shape. It will sit behind the current parsers, not in front of them: rules first, model only where rules come up empty.


⬆️ Upgrading from 1.x

The old Selenium class still works:

pip install facebook-page-info-scraper[selenium]
from facebook_page_info_scraper import FacebookPageInfoScraper
FacebookPageInfoScraper(url).get_page_info()

Either new engine is a recommended replacement — same idea, much faster.

Two output differences:

  • page_rate and page_review_number used to be swapped. They are correct now.
  • location was a country name; the new address is the full street address.

🤝 Contributing

Contributions are welcome. If you find an issue or have a suggestion, please open an issue or submit a pull request on GitHub.

📝 Notes

  • Only public pages. Nothing behind a login.
  • Be reasonable with threads — this hits Facebook from your IP.
  • Scraping Facebook is against their Terms of Service. Use accordingly.

License

MIT — see LICENSE.txt.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

facebook_page_info_scraper-2.0.0.tar.gz (30.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

facebook_page_info_scraper-2.0.0-py3-none-any.whl (29.7 kB view details)

Uploaded Python 3

File details

Details for the file facebook_page_info_scraper-2.0.0.tar.gz.

File metadata

File hashes

Hashes for facebook_page_info_scraper-2.0.0.tar.gz
Algorithm Hash digest
SHA256 63bbf31f143a3e5739fe41c55376e85bb60a28f1a7b81b4451119cd041fe1ea6
MD5 53ac2ef1405522261688a9611b3d1175
BLAKE2b-256 089f97908ab8311744295b77187f4a8d1f3097f735f20000120ca716009b722c

See more details on using hashes here.

Provenance

The following attestation bundles were made for facebook_page_info_scraper-2.0.0.tar.gz:

Publisher: publish-to-pypi.yml on wael-sudo2/facebook-page-info-scraper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file facebook_page_info_scraper-2.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for facebook_page_info_scraper-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c550eb01f3a0d0efc523d2b61ab7a01647b12d61d44ff75ebc082ae29cd1585
MD5 0fa22b9238ac2235d42c0157e4f0c31f
BLAKE2b-256 734359213809092e5bc70a972f0e46b278ed8eabb048190b6f05257e9eb473a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for facebook_page_info_scraper-2.0.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on wael-sudo2/facebook-page-info-scraper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page