All notable changes to this Actor will be documented here.
[2.2] — 2026-07-18
Performance (2-3× faster, 3× cheaper bandwidth)
Cookie warm-up in profile fetch — eliminates login walls that were causing
fallback to embed (extra request). Single desktop request now succeeds reliably.
Stop-on-first-success: no more multiple strategy attempts per profile.
Embed follower lookup skipped when desktop already found followers.
Embed fallback skipped entirely in fast mode.
Default timeout reduced 45s → 20s.
Default concurrency raised 10 → 15.
Fast mode caps at 300 KB (gets name, followers, likes, verified, website).
Improved login wall detection (mbasic, mobile, OG title patterns).
Added lm.facebook.com link extractor for mbasic external URLs.
~0.28 MB residential per profile (was ~0.8+ with multi-strategy + embed).
5-6s for 3 profiles (was 15-30s).
Same output schema, same $0.004 per-result billing.
[2.1] — 2026-07-17
Fixed (Facebook 2026 anti-bot breakage)
Removed Accept-Encoding: br — Facebook was returning brotli that couldn't be
decoded, producing garbage. This was the root cause of the scraper returning
empty records.
Desktop cookie warm-up (hit facebook.com root first) — Facebook now returns
400 to cold desktop requests without a datr cookie.
Refreshed to Chrome 150 User-Agent + Sec-Fetch / sec-ch-ua headers.
Read window raised 120 KB → 900 KB: contacts/category/verification are embedded
deep in the page's inline JSON (~600-850 KB), out of reach of the old cap.
Added / improved extraction (no login)
Website extraction now handles the 2026 inline-JSON format (l.facebook.com/l.php
with \u0025 unicode-escaped percent encoding) and the direct external_url field.
category parsed from category_name / delegate_page inline JSON.
verified made strict (explicit is_verified:true JSON) — fixes false positives
from CSS --badge-* variables that marked every page verified.
Googlebot UA added as a third fallback strategy.
New features (competitor parity)
Keyword search — supply searchKeywords (+ optional searchLocation) instead
of URLs; the actor discovers matching public Facebook profiles/pages via Google
(Apify GOOGLE_SERP proxy) and scrapes each. profileUrls is now optional.
Google email enrichment — when a page exposes no public email in its FB HTML,
search Google for it (no login). Toggle with enrichEmailViaGoogle.
Email domain filter — emailDomains keeps only emails on chosen domains
(e.g. gmail.com, a company domain).
[2.0] — 2026-06-21
Store listing (SEO) & growth
Retitled to Facebook Page Scraper — Emails, Phone, Contacts & Posts (No Login)
and rewrote the store description around high-intent keywords (emails, phone,
contacts, posts, no login) to improve Store ranking.
Added a friendly end-of-run rating prompt in the log.
[1.9] — 2026-06-21
Cost (experiment, reverted)
Tested an 80 KB read cap; it reduced data completeness AND raised cost
(broke the skip-mobile fast path), so the proven 120 KB cap was restored.
[1.8] — 2026-06-21
Cost
Posts-scraping warm-up no longer downloads the facebook.com body (only the
datr cookie from headers is needed) — lower residential bandwidth, keeps
scrapePosts runs profitable per result.
[1.7] — 2026-06-21
Performance
~40% faster per profile: when the first (desktop) fetch already yields a
complete record (follower count + name), the mobile variant and embed
fallback are skipped — one residential request instead of two.
maxConcurrency cap raised 10 → 20 (default 3 → 5) for higher throughput on
large URL lists; residential IPs rotate per request.
[1.6] — 2026-06-21
Added — recent posts, engagement & video (PAGE CONTACT INFO niche)
scrapePosts (opt-in) — alongside page contact info, pull the page's
recent public posts: text, reactions / comments / shares, photos, videos
with direct MP4 URLs, captions/transcript URL and author. Emitted as extra
rows with type: "post", billed per post.
Post filters: sinceDays (recency) and postKeyword (text contains).
maxPosts caps posts per page. Posts are deduped with the same engine.
ponytail: logged-out pages expose only a window of recent posts (full feed is
behind login).
[1.5] — 2026-06-21
Added — PAGE CONTACT INFO niche differentiators
Deduplication — duplicate input URLs (vanity vs numeric profile.php,
trailing-slash, locale-prefixed, m./www . variants all collapse) are dropped
up-front, and duplicate output profiles (same Facebook ID) are skipped, so
the same page is never scraped or billed twice. (dedupe, default on.)
Retry control — maxRetries (default 2) retries a failed/blocked
profile with a fresh proxy IP and exponential backoff.
Real-time webhook — notifyWebhookUrl POSTs each scraped profile as JSON
the moment it's found (Zapier / Make / n8n / Slack / Discord).
[1.4] — 2026-06-07
Improved — audience metrics fallback
When Facebook hides the follower count for logged-out requests (common on
some large pages), audienceSize and the activity score now fall back to
page likes, so big pages are no longer mis-classified as unknown size.
Found via a 25-profile stress test (100% success rate).
[1.3] — 2026-06-07
Removed
Cookies mode (posts / people-search / private profiles) was removed. The
actor stays strictly no-login: public profile & page metadata only.
Recon confirmed posts and people-search are login-gated on Facebook, so they
are out of scope for a cookie-free scraper.
[1.1] — 2026-06-07
Added — competitor-parity fields (no login, from the same fetch)
facebookId — numeric page/profile ID (from app-link meta / JSON-LD).
Numeric ID input — accepts bare IDs and /profile.php?id=... (URL↔ID),
fixing a bug where the id query was dropped on normalize.
coverPhoto, alternateName, gender (best-effort).
priceRange — business price band ($/$$/$$$) for pages.
isComplete / wasBlocked transparency flags on every record.
These close the data gaps versus curious_coder (price/cover/ID),
devwithbobby (engagement/audience/flags) and lazyscraper (numeric ID).
[2.0] — 2026-05-22
Fixed — actor was returning errors for all 19 paying users
The previous data pipeline stopped working after Facebook tightened its
anti-bot protection in early 2026, leaving every run failing with
Failed to fetch website content. v2.0 replaces the entire backend with
direct Facebook scraping.
Changed
Direct fetch — no third-party scraping API
Multi-strategy fallback — cycles through mbasic, mobile, desktop,
Googlebot UA, and embed iframe until one succeeds
Apify residential proxy by default — datacenter IPs are heavily
rate-limited by Facebook
apify SDK instead of legacy apify-client async pattern
Title now reads "Facebook Profile Scraper | $4/1K | No Login (Real-Time)"
with v2.0 features in description
Added — major intelligence upgrade
profileType detection — page / profile / group / unknown
verified — blue verification badge boolean
emails[] + primaryEmail — public emails scraped from page text,
JSON-LD, and Open Graph meta. Filtered through 30+ Facebook CDN blacklist
phones[] + primaryPhone — public phones with regex normalisation
activityScoreReasons[] — every contributing signal in plain English
activityTier — small (<30) / growing (30-49) / established (50-69)
/ major (70+)
locale — Open Graph language tag for international segmentation
fetchStrategy — diagnostic field showing which endpoint succeeded
fetchStatus — HTTP status of the successful fetch
Removed
All "extract*" boolean toggles from input schema — every field is now always
computed because they're free (single HTML fetch). Reduces input complexity
from 14 fields to 5.
Legacy ALL_COLUMNS / extractColumns payload construction
Direct requests / ThreadPoolExecutor runtime — replaced with httpx +
asyncio for proper async fetch with proxy rotation
Migration
v1 callers continue to work — profileUrls is the only required input.
The new fields are additive. Old fields like username, fullName, bio,
followerCount, profileUrl, email, website, category are still
present (some renamed: email → emails[0] / primaryEmail,
website → websites[0] / primaryWebsite).
[1.0] — 2026-04-XX
Added
Initial release
Multi-field configurable extraction (now superseded — all fields free in v2)