<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mentat Logic</title>
    <description>The latest articles on DEV Community by Mentat Logic (@mentat_logic).</description>
    <link>https://dev.to/mentat_logic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4036560%2Ffed9002e-5a7a-4c75-a344-5f9ef29b9b5d.png</url>
      <title>DEV Community: Mentat Logic</title>
      <link>https://dev.to/mentat_logic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mentat_logic"/>
    <language>en</language>
    <item>
      <title>Reading a comment section like an analyst: coordination signals without calling anyone a bot</title>
      <dc:creator>Mentat Logic</dc:creator>
      <pubDate>Mon, 20 Jul 2026 17:15:25 +0000</pubDate>
      <link>https://dev.to/mentat_logic/reading-a-comment-section-like-an-analyst-coordination-signals-without-calling-anyone-a-bot-24b6</link>
      <guid>https://dev.to/mentat_logic/reading-a-comment-section-like-an-analyst-coordination-signals-without-calling-anyone-a-bot-24b6</guid>
      <description>&lt;p&gt;Advertisers ask it after every campaign: "did my budget buy real engagement?" PR teams ask it during every pile-on: "is this organic?" Here is how to read a comment export like an analyst — the signals that mean something, the ones that don't, and the honest limit nobody selling "bot scores" will tell you about.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, retire the word "bot"
&lt;/h2&gt;

&lt;p&gt;Three different things hide behind it, and they leak differently:&lt;/p&gt;

&lt;p&gt;Tier 1 — automated accounts. Scripts. They leak automation: machine-even posting intervals, generated-name patterns (Firstname Lastname8123 cohorts), impossible hours held for weeks.&lt;/p&gt;

&lt;p&gt;Tier 2 — cheap operated fakes. Real humans, fake accounts, paid per comment. This is the tier that actually floods commercial and political campaigns — and it defeats every automation signal, because the typing is human. What it cannot hide is coordination: the campaign brief synchronizes them. They arrive in bursts, they paraphrase the same talking point, they repeat themselves across posts, they reply to each other to lift the thread.&lt;/p&gt;

&lt;p&gt;Tier 3 — professionally managed personas. Full histories, varied interests, natural language. Here is the honest limit: in engagement data alone, these are indistinguishable from real people by design. Anyone selling certainty about this tier is selling vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The signals worth trusting (each with its evidence)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Timing bursts — many distinct accounts commenting on one post inside a tight window. Evidence: the timestamp cluster. One burst is an influencer share; recurring bursts with overlapping membership are a pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplicate and near-duplicate text — identical or lightly-edited comments across accounts. Copy-paste with cosmetic edits clusters beautifully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talking-point convergence — distinct accounts using the same rare phrase inside a window. Softer than duplication, still leaky.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cross-post repetition — one account, one text, many posts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Machine-regular cadence — posting intervals too even for a human (needs several comments per account to mean anything).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Burst-only participation — accounts that exist in your data only inside bursts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mutual reply-chains — pairs boosting each other's comments to lift thread ranking.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The two disciplines that keep the analysis honest
&lt;/h2&gt;

&lt;p&gt;Insufficient data is an answer. An account with one comment cannot be judged — not "probably fine," not "suspicious." Insufficient signal. Most accounts in most datasets land here, and saying so is what makes the rest of the analysis credible.&lt;/p&gt;

&lt;p&gt;Signals describe behaviour, never persons. "This account's comments sit inside two bursts and a duplicate cluster" is evidence. "This account is a bot" is a guess wearing a costume — and a legal exposure if you put it in a client deliverable. Report patterns with evidence attached; let humans decide what to do about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The procedure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
1. Deduplicate comments first (same comment arrives twice via URL variants).

2. Group by account; count; below threshold -&amp;gt; INSUFFICIENT SIGNAL, stop.

3. Detect bursts per post (window + distinct-account minimum).

4. Cluster normalized text (exact, then near-duplicate, then rare-phrase).

5. Check cadence regularity, cross-post repeats, reply-chain pairs.

6. Levels from accumulated evidence: NO SIGNALS / WEAK / MULTIPLE / STRONG.

7. Print into the deliverable: the coverage block, the evidence per flag,

   and what the method CANNOT detect (Tier 3). The limits are the credibility.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Disclosure: I build a tool that runs exactly this — the &lt;a href="https://apify.com/mentat-logic/mentat-authenticity-audit" rel="noopener noreferrer"&gt;Engagement Authenticity Audit&lt;/a&gt; processes any Facebook comments export ($0.66 per 1,000 unique comments, deduplicated first; free demo with a planted burst you can watch it catch — and a single-comment account you can watch it refuse to judge). Its siblings: the free &lt;a href="https://apify.com/mentat-logic/mentat-resolver" rel="noopener noreferrer"&gt;Page Identity Resolver&lt;/a&gt; and &lt;a href="https://apify.com/mentat-logic/mentat-page-compare" rel="noopener noreferrer"&gt;Page Compare&lt;/a&gt;. The procedure above works without any of them — that's rather the point.&lt;/p&gt;

</description>
      <category>marketing</category>
      <category>datascience</category>
      <category>socialmedia</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to compare Facebook pages without fooling yourself</title>
      <dc:creator>Mentat Logic</dc:creator>
      <pubDate>Mon, 20 Jul 2026 09:12:53 +0000</pubDate>
      <link>https://dev.to/mentat_logic/how-to-compare-facebook-pages-without-fooling-yourself-2l57</link>
      <guid>https://dev.to/mentat_logic/how-to-compare-facebook-pages-without-fooling-yourself-2l57</guid>
      <description>&lt;p&gt;&lt;em&gt;Page-vs-page comparisons drive real decisions — PR retainers, ad placements, competitive reviews, "why is their engagement triple ours" meetings. Most of them are quietly wrong before the analysis even starts. Here are the five ways they lie, and a procedure that doesn't. It works with any scraper's export and no particular tool.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The five ways comparisons lie
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Duplicates get counted twice. The same post arrives as /posts/301 and /posts/301?ref=share, from &lt;a href="http://www" rel="noopener noreferrer"&gt;www&lt;/a&gt;. and from m. — and naive counting books it twice. Worse, this isn't random noise: pages that cross-post and push share links get inflated systematically. Your "most active page" may just be your most duplicated one.&lt;/li&gt;
&lt;li&gt;The windows aren't equal. One page was scraped deeper into the past than another (scrapers paginate unevenly), so page A gets 90 days of history and page B gets 30 — then someone compares totals. Align the window first, and say what it is.&lt;/li&gt;
&lt;li&gt;The mean worships one viral post. A page with 49 dead posts and one 10,000-engagement hit "averages" 200 per post. Report the median for typical performance and list the top posts separately — they're different facts and both matter.&lt;/li&gt;
&lt;li&gt;Absent fields become zeros. Mobile exports often lack shares entirely. Treat missing as zero and that page "has no shares" — a data artifact promoted to a finding. Absent data should render as absent (&lt;strong&gt;"—"&lt;/strong&gt;), never as 0, and the report should say which fields were absent where.&lt;/li&gt;
&lt;li&gt;Nobody states the coverage. "We compared the pages" — on how many rows? After removing how many duplicates? Over what window, in whose timezone? How many posts had no readable date? A comparison that can't answer these isn't evidence; it's vibes with a chart.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The procedure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
1. Canonicalize every URL first (hosts folded, tracking params stripped,

   identity params kept) — see "The Facebook URL Zoo" for the full rules.

2. Deduplicate on the canonical post key. Record how many you removed.

3. Align the comparison window across all pages; state it, with timezone.

4. Per page: post count, total engagement gained, MEDIAN engagement,

   and top posts listed separately.

5. Render absent fields as "—", and note which pages lacked which fields.

6. Print the coverage block INTO the deliverable: rows in, duplicates

   removed, window, dateless rows, fields absent. The method is part of

   the report, not a footnote you keep to yourself.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this matters most in PR and advertising
&lt;/h2&gt;

&lt;p&gt;If you make your living on these numbers, the deliverable is the argument. A competitive audit that states its coverage and shows its dedup survives the hostile question in the client meeting; one that can't explain its denominators dies there, and takes your credibility with it. And if you're an advertiser vetting pages for placements or partnerships: duplicate-inflated engagement is precisely how a mediocre page is made to look lively. The procedure above is how you check before the money moves.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I build tools that implement exactly this. &lt;a href="https://apify.com/mentat-logic/mentat-page-compare" rel="noopener noreferrer"&gt;Mentat Page Compare&lt;/a&gt; runs the whole procedure on any posts-scraper export and produces a client-ready HTML report — $3.99 per 1,000 unique posts (deduplicated first, so you never pay twice for the same post; platform compute included; the demo is free). Its free sibling, the &lt;a href="https://apify.com/mentat-logic/mentat-resolver" rel="noopener noreferrer"&gt;Facebook Page Identity Resolver&lt;/a&gt;, handles step 1-2 alone. The full URL taxonomy is in &lt;a href="https://dev.to/mentat_logic/the-facebook-url-zoo-every-page-link-format-and-how-to-canonicalize-them-4jfe"&gt;The Facebook URL Zoo&lt;/a&gt;. The procedure works without any of them — that's rather the point.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>datascience</category>
      <category>marketing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Facebook URL Zoo: every page-link format and how to canonicalize them</title>
      <dc:creator>Mentat Logic</dc:creator>
      <pubDate>Sun, 19 Jul 2026 13:34:51 +0000</pubDate>
      <link>https://dev.to/mentat_logic/the-facebook-url-zoo-every-page-link-format-and-how-to-canonicalize-them-4jfe</link>
      <guid>https://dev.to/mentat_logic/the-facebook-url-zoo-every-page-link-format-and-how-to-canonicalize-them-4jfe</guid>
      <description>&lt;p&gt;&lt;em&gt;If you scrape or analyze Facebook data, the same page will arrive under half a dozen different URLs — and if you count anything before resolving that, your numbers are quietly wrong. This is the reference I wish had existed: the formats, the traps, and a canonicalization procedure that never guesses.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your counts are wrong
&lt;/h2&gt;

&lt;p&gt;Pull posts from any Facebook scraper and look at the page URLs. The same fish market shows up as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.facebook.com/HelensFreshMarket
https://m.facebook.com/helensfreshmarket/
https://www.facebook.com/profile.php?id=100077000000001
https://www.facebook.com/p/Helens-Fresh-Market-100077000000001/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Group by URL and you have four "pages," each with a quarter of the real engagement. Every downstream number — rankings, share-of-voice, averages — inherits the error. Post URLs have the same disease: the same post arrives with and without tracking parameters, from mobile and desktop hosts, and through share redirects.&lt;/p&gt;

&lt;h2&gt;
  
  
  The zoo, part 1: hosts
&lt;/h2&gt;

&lt;p&gt;All of these serve the same content and must be folded together:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;www.facebook.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;canonical desktop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;facebook.com (bare)&lt;/td&gt;
&lt;td&gt;redirects to www&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;m.facebook.com&lt;/td&gt;
&lt;td&gt;mobile web (very common in scraped data)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mbasic.facebook.com&lt;/td&gt;
&lt;td&gt;legacy low-bandwidth mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;web.facebook.com&lt;/td&gt;
&lt;td&gt;regional variant (common in Africa/Asia exports)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;touch.facebook.com&lt;/td&gt;
&lt;td&gt;legacy touch interface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: fold every host to &lt;a href="http://www.facebook.com" rel="noopener noreferrer"&gt;www.facebook.com&lt;/a&gt;, force https, drop the trailing slash.&lt;/strong&gt; Trivial, and it already collapses a third of the zoo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The zoo, part 2: page-identity URLs
&lt;/h2&gt;

&lt;p&gt;These are the formats that name a page (strongest evidence first):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Identity signal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;profile.php?id={N}&lt;/td&gt;
&lt;td&gt;/profile.php?id=100077…&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;numeric ID — authoritative&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/p/{Name}-{N}/&lt;/td&gt;
&lt;td&gt;/p/Helens-Fresh-Market-100077…/&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;numeric ID — authoritative&lt;/strong&gt; (newer format; the trailing number is the page ID)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/people/{Name}/{N}/&lt;/td&gt;
&lt;td&gt;/people/Helen-M/100077…/&lt;/td&gt;
&lt;td&gt;numeric ID — authoritative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/pages/{Name}/{N}&lt;/td&gt;
&lt;td&gt;legacy&lt;/td&gt;
&lt;td&gt;numeric ID — authoritative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/{vanity}&lt;/td&gt;
&lt;td&gt;/HelensFreshMarket&lt;/td&gt;
&lt;td&gt;slug — reliable but &lt;strong&gt;case-varies&lt;/strong&gt;; case-fold before comparing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/pg/{vanity}/…&lt;/td&gt;
&lt;td&gt;legacy page-tab wrapper&lt;/td&gt;
&lt;td&gt;slug after stripping /pg/&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule 2: extract identity by hierarchy — a numeric ID always outranks a slug.&lt;/strong&gt; When both are observed for the same entity (a slug URL and a profile.php?id= URL that share posts or metadata), the numeric ID is the canonical key and the slug becomes an alias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 3: slugs are case-insensitive — case-fold before comparing.&lt;/strong&gt; HelensFreshMarket and helensfreshmarket are the same page; a case-sensitive groupby splits them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The zoo, part 3: post URLs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;/{vanity}/posts/{id}&lt;/td&gt;
&lt;td&gt;/helensfreshmarket/posts/101&lt;/td&gt;
&lt;td&gt;id may be numeric or an opaque pfbid… token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;permalink.php?story_fbid={S}&amp;amp;id={P}&lt;/td&gt;
&lt;td&gt;desktop permalink&lt;/td&gt;
&lt;td&gt;the &lt;strong&gt;params are the identity&lt;/strong&gt; — keep them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;story.php?story_fbid={S}&amp;amp;id={P}&lt;/td&gt;
&lt;td&gt;mobile permalink&lt;/td&gt;
&lt;td&gt;same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/groups/{g}/posts/{id}&lt;/td&gt;
&lt;td&gt;group post&lt;/td&gt;
&lt;td&gt;group ≠ page; keep the distinction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;photo.php?fbid={N} / /photo/?fbid={N}&lt;/td&gt;
&lt;td&gt;photo post&lt;/td&gt;
&lt;td&gt;fbid is the identity param&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/watch/?v={N}&lt;/td&gt;
&lt;td&gt;video watch page&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;carries no page identity&lt;/strong&gt; (see traps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/reel/{id}&lt;/td&gt;
&lt;td&gt;reel&lt;/td&gt;
&lt;td&gt;post-level only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/share/p/{token}/, /share/v/{token}/&lt;/td&gt;
&lt;td&gt;share redirect&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;opaque&lt;/strong&gt; (see traps)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule 4: for deduplication, strip tracking parameters but keep identity parameters.&lt;/strong&gt; Strip: ref, refid, fbclid, mibextid, rdid, utm_*, &lt;strong&gt;tn&lt;/strong&gt;, comment_id, notif_id, notif_t, locale. Keep: story_fbid, id, fbid, v. The same post with and without ?ref=share&amp;amp;utm=x is one post; the same path with a different story_fbid is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The traps (where guessing corrupts datasets)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trap 1 — display names are not identity.&lt;/strong&gt; Two pages named "Caladan Bay Tours" can be genuinely different entities (rebrand, fan page, impersonator, franchise). Merging on display name is how datasets rot. The correct behavior is to report the collision as a possible-same-entity hint with the evidence, and let a human decide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trap 2 — /watch?v= links carry no page identity.&lt;/strong&gt; The URL names a video, not a page. Attribute it to a page only if the row carries separate page metadata; otherwise it is honestly unresolvable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trap 3 — share links are opaque.&lt;/strong&gt; /share/p/{token}/ is a server-side redirect; the token doesn't encode the destination. Offline, you cannot resolve it — flag it, don't guess it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trap 4 — renames.&lt;/strong&gt; A page that changed its vanity slug between scrapes, and never exposed its numeric ID, looks like two pages. Without an ID observation there is no safe automatic merge; surface it, don't force it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trap 5 — pfbid tokens.&lt;/strong&gt; Modern post IDs are opaque pseudonymized tokens. Treat them as exact-match strings only; never parse meaning out of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The procedure, end to end
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for each row:
  1. fold host → www.facebook.com, https, strip trailing slash
  2. classify URL: page-identity form vs post form
  3. page identity:
       numeric ID present → key = fb:{numeric}
       else vanity slug   → key = fb:{casefold(slug)}
       else               → UNRESOLVED (keep the URL as evidence)
  4. post dedup key: canonical path + kept identity params
       (tracking params stripped)
  5. merge pages only when keys match
       same display name, different keys → report hint, do NOT merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The principle underneath: &lt;strong&gt;an unresolved row with its evidence attached is useful; a silently guessed merge is poison.&lt;/strong&gt; Every downstream consumer can act on "here are 3 rows I couldn't resolve, and why" — nobody can undo a wrong merge they never knew happened.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I maintain a small free tool that implements exactly this procedure (including the refusals) for any posts-scraper export — &lt;a href="https://apify.com/mentat-logic/mentat-resolver" rel="noopener noreferrer"&gt;Facebook Page Identity Resolver &amp;amp; URL Deduplicator&lt;/a&gt; on Apify, with a 3-second no-signup demo. But the procedure above works fine without it — that's rather the point.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>datascience</category>
      <category>facebook</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
