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.

Download files

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

Source Distribution

facebook_posts_details-0.1.0.tar.gz (39.2 kB view details)

Uploaded Source

Built Distribution

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

facebook_posts_details-0.1.0-py3-none-any.whl (31.8 kB view details)

Uploaded Python 3

File details

Details for the file facebook_posts_details-0.1.0.tar.gz.

File metadata

  • Download URL: facebook_posts_details-0.1.0.tar.gz
  • Upload date:
  • Size: 39.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for facebook_posts_details-0.1.0.tar.gz
Algorithm Hash digest
SHA256 79218cecf7dccb2a1eeca06b7e33ad1bb041afc4a04b4d94f9e622ec055a0bee
MD5 965cc4907dde379e309204a2509b4b0e
BLAKE2b-256 b2fbdc7b034a48af6b836acff84e1965f834af01ad90471d5a946b22619935ea

See more details on using hashes here.

File details

Details for the file facebook_posts_details-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for facebook_posts_details-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ccdeebf5e932a56168b21598bca35161b3af5bc3c327de99e505246a6c7e40d0
MD5 9b8f766b37c58aa58200d18564ad7cfc
BLAKE2b-256 a969cac8404d8dc21f5340e7f1ae77fcdfc109fda2d34200efeccb63effcbc59

See more details on using hashes here.

Supported by

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