Skip to main content

facebook-posts-details

PyPI Python License Downloads

Extract public data from Facebook post, reel, video, photo, story and profile URLs. No login, no API key, no browser.

Get the likes, comments, shares, views, text, images, video URL and author of any public Facebook post or reel — and the name, bio, followers, category and profile picture of any public profile or page — with one function call.

A lightweight alternative to the Facebook Graph API when all you need is public data: no app review, no access token, no rate-limit dashboard.

Install

pip install facebook-posts-details

That is all you need — pip pulls the dependencies automatically.

Quick start

import facebook_posts_details as fb

post = fb.post_data("https://www.facebook.com/reel/941309212326403")

post["likes_count"]      # 104378
post["comments_count"]   # 292
post["post_text"]        # '😎😎…..'
post["video_url"]        # 'https://video-del3-1.xx.fbcdn.net/...'
profile = fb.profile_data("https://www.facebook.com/zuck")

profile["name"]          # 'Mark Zuckerberg'
profile["followers"]     # 121000000
profile["bio"]           # 'Bringing the world closer together.'

Let the URL pick the right one for you:

data = fb.scrape(url)

Functions

Call Returns
fb.post_data(url) a post, reel, video, photo or story
fb.profile_data(url) a profile or page
fb.profile_about(url) every "About" tab, merged into one dict
fb.scrape(url) whichever of the above fits the URL

All of them return None if the page could not be read, so one bad URL never stops a batch:

for url in urls:
    data = fb.scrape(url)
    if data is None:
        continue
    ...

Also fetch the author's profile

url = ("https://www.facebook.com/middlestumpcric/posts/"
       "pfbid02UgzMPp1nyS1gzQt9RNBG1AaiqJ1eZWAVSbt5rHkTw7jod5JLNCAD8USh1wkxVYGPl")

post = fb.post_data(url, with_profile=True)

post["user"]["name"]         # 'Middle Stump Cricket'
post["user"]["followers"]    # 1400000

Costs one extra request. Without the flag, post["user"] is {}.

Not every author publishes every field — many personal profiles hide their follower count, in which case post["user"]["followers"] is None while post["user"]["name"] still works.

What you get back

Every dict has a fixed set of keys. A field that could not be found is None (or an empty list/dict), never missing — so post["likes_count"] never raises a KeyError.

The examples below are illustrative and come from different posts: no single post has every field. views_count appears on some videos and reels, transcript only on videos that have one, video_url only where there is a video.

post_data(url)

Key Example
url 'https://www.facebook.com/reel/941309212326403'
post_id '941309212326403'
post_type 'reel' — one of post, reel, video, photo, story
post_text '😎😎…..'
publish_date 1786517734 (unix seconds)
publish_date_iso '2026-08-12T06:55:34+00:00'
likes_count 104378
comments_count 292
share_count 1000
views_count 9400000
post_images [{"url": "https://...", "caption": "May be an image of ..."}]
video_url 'https://video-del3-1.xx.fbcdn.net/...'
transcript 'What does Rahul Gandhi do every...'
name 'Sucha Shooter'
profile_url 'https://www.facebook.com/sucha.shooter.965'
profile_image 'https://...'
user {}, or the author's profile with with_profile=True

profile_data(url)

Key Example
url 'https://www.facebook.com/zuck'
profile_id 'zuck' (username, or the numeric id)
profile_id_number '4'
name 'Mark Zuckerberg'
bio 'Bringing the world closer together.'
category_name 'Public figure'
gender 'MALE'
is_verified True
followers 121000000
followers_text '121M followers' (as displayed)
following None
following_text None
profile_pic 'https://...'
cover_photo 'https://...'
about_section {"intro": {"website": [{"value": "x.com", "url": "https://..."}]}}
photos ['https://...', ...]

Good to know:

  • Counts are always int or None — never a string like "1.4M". The displayed form is kept in followers_text / following_text.
  • Reels only publish a rounded share count, so share_count on a reel is rounded the same way the page shows it (1000 for "1K"). Likes and comments are exact.
  • post_images entries are always {"url", "caption"}. caption is None when Facebook has no real description for the image.

Command line

facebook-posts-details <url>                    # prints JSON
facebook-posts-details <url1> <url2> ...        # several at once
facebook-posts-details <url> --summary          # short readable output
facebook-posts-details <url> --with-profile     # include the author's profile
facebook-posts-details <url> --proxy http://user:pass@host:port
facebook-posts-details <url> --kind profile     # skip URL auto-detection
facebook-posts-details <url> --timeout 60 --retries 3
facebook-posts-details <url> -v                 # show progress on stderr

JSON goes to stdout and messages go to stderr, so this works cleanly:

facebook-posts-details <url> | jq .likes_count

Exit status is 1 if any URL returned nothing.

Proxies

No proxy is used unless you pass one. Proxies work the same way as in requests, and are accepted by post_data, profile_data, profile_about, scrape and the CLI (--proxy).

# one URL, used for both http and https
fb.post_data(url, proxy="http://user:pass@1.2.3.4:8080")
fb.post_data(url, proxy="socks5://1.2.3.4:1080")

# a scheme-less value is treated as http
fb.post_data(url, proxy="1.2.3.4:8080")

# or a requests-style mapping
fb.post_data(url, proxy={"http": "http://1.2.3.4:8080",
                         "https": "http://1.2.3.4:8080"})

Examples

Without a proxy

The normal flow — nothing to configure.

import facebook_posts_details as fb

url = "https://www.facebook.com/reel/941309212326403"
post = fb.post_data(url)

if post is None:
    print("could not read that page")
else:
    print(post["name"], "-", post["post_text"])
    print(post["likes_count"], "likes,", post["comments_count"], "comments")
    for image in post["post_images"]:
        print(image["url"])

With a proxy

Pass proxy= to the same call. Everything else is identical.

import facebook_posts_details as fb

PROXY = "http://user:pass@1.2.3.4:8080"

url = "https://www.facebook.com/reel/941309212326403"
post = fb.post_data(url, proxy=PROXY)

print(post["likes_count"], post["comments_count"])

Several URLs, with a different proxy each time

Rotation is up to you — just pass a different proxy per call.

import itertools
import facebook_posts_details as fb

PROXIES = [
    "http://user:pass@1.2.3.4:8080",
    "http://user:pass@5.6.7.8:8080",
]
URLS = [
    "https://www.facebook.com/reel/941309212326403",
    "https://www.facebook.com/zuck",
]

pool = itertools.cycle(PROXIES)

for url in URLS:
    data = fb.scrape(url, proxy=next(pool))
    if data is None:
        print("failed:", url)
        continue
    print(data.get("name"), data.get("likes_count") or data.get("followers"))

To run the same loop without proxies, drop the argument:

    data = fb.scrape(url)

A post plus its author, saved to JSON

import json
import facebook_posts_details as fb

url = ("https://www.facebook.com/middlestumpcric/posts/"
       "pfbid02UgzMPp1nyS1gzQt9RNBG1AaiqJ1eZWAVSbt5rHkTw7jod5JLNCAD8USh1wkxVYGPl")

post = fb.post_data(
    url,
    with_profile=True,          # also fetch the author's profile
    proxy=None,                 # or "http://user:pass@host:port"
    timeout=60,
    retries=3,
)

with open("post.json", "w", encoding="utf-8") as f:
    json.dump(post, f, indent=2, ensure_ascii=False)

print(post["name"], "->", post["user"]["followers"], "followers")
# Middle Stump Cricket -> 1400000 followers

Command line, with and without a proxy

# without
facebook-posts-details "https://www.facebook.com/reel/941309212326403" --summary

# with
facebook-posts-details "https://www.facebook.com/reel/941309212326403" \
    --proxy http://user:pass@1.2.3.4:8080 --summary

Timeouts and retries

fb.post_data(url, timeout=60, retries=3)

Or change the defaults for every call:

fb.config.DEFAULT_TIMEOUT = 60     # default 30 seconds
fb.config.DEFAULT_RETRIES = 3      # default 2 attempts

Errors

Nothing is printed to stdout. Failures are logged and the call returns None. To see why something failed:

import logging
logging.basicConfig(level=logging.DEBUG)

Exceptions are only raised for programming mistakes, e.g. fb.InvalidURL if you pass a kind that does not exist.

Requirements

  • Python 3.8 or newer
  • tls-client3 — installed automatically by pip

Legal

Reads only publicly accessible pages, exactly as a logged-out browser would. You are responsible for complying with Facebook's Terms of Service and any law that applies to you. Provided as-is under the MIT licence.

Metadata

Release files for facebook-posts-details 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for facebook-posts-details 0.1.0
File Size Uploaded
facebook_posts_details-0.1.0.tar.gz 39.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for facebook-posts-details 0.1.0
File Interpreter ABI Platform
facebook_posts_details-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 71.0 kB

Release files / facebook_posts_details-0.1.0.tar.gz

Download URL facebook_posts_details-0.1.0.tar.gz
Size 39.2 kB
Tags Source
SHA-256 checksum
How to use checksums
79218cecf7dccb2a1eeca06b7e33ad1bb041afc4a04b4d94f9e622ec055a0bee
BLAKE2b-256 checksum
How to use checksums
b2fbdc7b034a48af6b836acff84e1965f834af01ad90471d5a946b22619935ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / facebook_posts_details-0.1.0-py3-none-any.whl

Download URL facebook_posts_details-0.1.0-py3-none-any.whl
Size 31.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ccdeebf5e932a56168b21598bca35161b3af5bc3c327de99e505246a6c7e40d0
BLAKE2b-256 checksum
How to use checksums
a969cac8404d8dc21f5340e7f1ae77fcdfc109fda2d34200efeccb63effcbc59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page