{
  "data": {
    "id": "a6Lt5hJbeDo9CracC",
    "actId": "gCko1ssooveQ4r5cK",
    "userId": "NL4ThgItAwaoBlffQ",
    "startedAt": "2026-10-18T04:55:57.647Z",
    "finishedAt": "2026-10-18T04:56:10.823Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 13108,
      "runTimeSecs": 13.108,
      "computeUnits": 0.014564444444444444,
      "imageSizeBytes": 354362880
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "zifX0mkAFMHe8CatY",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Facebook Comment Thread Extractor\",\n  \"description\": \"Extract public comments and reply threads from Facebook posts, photos, reels, videos, and public group posts. Returns comment text, author details, per-reaction-type counts, timestamps, reply context, and the post's own comment totals. No login or cookies required.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"startUrls\": {\n      \"title\": \"Facebook URLs\",\n      \"type\": \"array\",\n      \"description\": \"Facebook post, photo, reel, video, Watch, or public group post URLs (one or more). Comment permalinks (URLs containing ?comment_id=) are accepted and resolved to their post; legacy story.php, permalink.php and share links are normalized automatically. Most public reels and videos are supported; a minority restricted by Facebook return no thread and are reported.\",\n      \"editor\": \"requestListSources\",\n      \"prefill\": [\n        {\n          \"url\": \"https://www.facebook.com/NASA/posts/pfbid025kwyoBjhFGUC22fC4Sies56D5xvd65ZHR5PYjHhc7XSzqGsxuWq2uDVriZNxWbeol\"\n        }\n      ],\n      \"sectionCaption\": \"Input\",\n      \"sectionDescription\": \"Provide one or more public Facebook URLs to scrape comments from.\"\n    },\n    \"maxItems\": {\n      \"title\": \"Max comments per URL\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of comment rows (including replies) to collect per URL. The run also stops when Facebook has no more comments or replies to serve.\",\n      \"default\": 100,\n      \"prefill\": 5,\n      \"minimum\": 1,\n      \"maximum\": 10000,\n      \"sectionCaption\": \"Limits\"\n    },\n    \"onlyCommentsNewerThan\": {\n      \"title\": \"Only comments newer than\",\n      \"type\": \"string\",\n      \"description\": \"Limit results to comments posted after this date. Accepts YYYY-MM-DD, a full ISO 8601 timestamp (e.g. 2024-06-15T12:00:00Z), or a relative value like '1 day', '2 weeks', '3 months', '1 year'. When set, comments are fetched newest-first so the filter can stop as soon as an older comment is reached. Leave blank to disable date filtering.\",\n      \"editor\": \"textfield\"\n    },\n    \"commentsMode\": {\n      \"title\": \"Comment ordering\",\n      \"type\": \"string\",\n      \"description\": \"Which comment view to scrape: MOST_RELEVANT (Facebook's ranked view), NEWEST (all comments, newest first), or ALL (Facebook's unfiltered ranked view, including comments its ranked view may hide).\",\n      \"enum\": [\n        \"ALL\",\n        \"NEWEST\",\n        \"MOST_RELEVANT\"\n      ],\n      \"enumTitles\": [\n        \"All comments (Facebook's unfiltered view)\",\n        \"Newest first\",\n        \"Most relevant (Facebook's ranked view)\"\n      ],\n      \"default\": \"ALL\",\n      \"prefill\": \"MOST_RELEVANT\"\n    },\n    \"includeNestedComments\": {\n      \"title\": \"Include replies\",\n      \"type\": \"boolean\",\n      \"description\": \"If true, also scrape reply rows under top-level comments (with parent/reply metadata). If false, only top-level comments are collected (faster).\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"maxReplyDepth\": {\n      \"title\": \"Max reply nesting depth\",\n      \"type\": \"integer\",\n      \"description\": \"How deep into reply threads to collect: 1 = direct replies to top-level comments only, 2 or more = also include deeper nested replies. Facebook serves reply threads with up to two nesting levels to anonymous visitors.\",\n      \"default\": 1,\n      \"prefill\": 1,\n      \"minimum\": 1,\n      \"maximum\": 5\n    }\n  },\n  \"required\": [\n    \"startUrls\"\n  ]\n}",
    "readme": "# Facebook Post & Group Comment Thread Extractor\n\nGet public comments and full reply threads from Facebook posts, photos, and public group posts. Returns comment text, author details, per-reaction-type counts, timestamps, attachment and mention data, plus the post's own comment totals — no login or cookies required.\n\n## What this actor does\n\n- Scrapes comments from public Facebook posts, photos, reels, videos, and public group posts, with full pagination (thousands of comments per post when Facebook serves them)\n- Reels and videos are followed through Facebook's canonical video permalink, with a strict check that the returned thread belongs to the requested video\n- Follows reply threads and includes nested replies (direct replies plus deeper nesting when Facebook returns it)\n- Three comment orderings: Facebook's ranked view, all comments, or newest first\n- Captures author details (name, profile picture, profile URL, ID), reaction totals and a per-reaction-type breakdown\n- Surfaces the parent post's context on every row: page name, post text, Facebook's total comment count, and the count visible to anonymous visitors\n- Filters results to comments posted after a given date\n- `reactionBreakdown`, `attachmentType`, `hashtags`, `mentions`, `groupCommentInfo` and similar optional fields are only added when Facebook's data carries them\n\n## Input\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `startUrls` | array | – | Required. Facebook post, photo, or public group post URLs. Comment permalinks (`?comment_id=`) are resolved to their post; legacy `story.php`, `permalink.php` and share links are normalized automatically |\n| `maxItems` | integer | `100` | Maximum number of comment rows (including replies) per URL; 1–10,000 |\n| `onlyCommentsNewerThan` | string | – | Date filter: `YYYY-MM-DD`, full ISO 8601, or relative (`1 day`, `2 weeks`, `3 months`, `1 year`). Comments are fetched newest-first so pagination stops early |\n| `commentsMode` | string | `ALL` | Comment ordering: `ALL` (Facebook's unfiltered view), `NEWEST` (newest first), or `MOST_RELEVANT` (Facebook's ranked view) |\n| `includeNestedComments` | boolean | `true` | Also collect reply rows under top-level comments (with parent/reply metadata). Turn off for faster, top-level-only runs |\n| `maxReplyDepth` | integer | `1` | Reply nesting depth to collect: `1` = direct replies only, `2`+ also includes deeper nested replies; 1–5 |\n\nAt least one URL in `startUrls` is required. Provide URLs as plain strings, `{ \"url\": \"...\" }` objects, or several URLs separated by spaces/newlines in one string.\n\n### Supported URL formats\n\n- **Posts**: `https://www.facebook.com/PageName/posts/1234567890`\n- **Posts (pfbid)**: `https://www.facebook.com/PageName/posts/pfbid0...`\n- **Legacy permalinks**: `story.php?story_fbid=...&id=...`, `permalink.php?...` (normalized automatically)\n- **Photos**: `https://www.facebook.com/photo?fbid=1234567890`, `photo.php?fbid=...`, `PageName/photos/...`\n- **Reels**: `https://www.facebook.com/reel/1234567890` (resolved through Facebook's video permalink)\n- **Videos**: `https://www.facebook.com/PageName/videos/1234567890`, `https://www.facebook.com/watch?v=1234567890`\n- **Public group posts**: `https://www.facebook.com/groups/groupname/permalink/1234567890/`, `groups/<id>/posts/<id>`\n- **Comment permalinks**: any post URL with `?comment_id=...` — the parent post's thread is returned\n- **Share links**: `https://www.facebook.com/share/p/...` (resolved through Facebook's redirect)\n- **Mobile URLs**: `m.facebook.com/...` links are normalized to `www`\n\nSome individual videos are restricted by Facebook and do not expose their comment thread to anonymous visitors; the actor reports that per video instead of guessing (see Limitations).\n\n### Example input\n\n```json\n{\n  \"startUrls\": [\n    { \"url\": \"https://www.facebook.com/NASA/posts/1234567890\" },\n    { \"url\": \"https://www.facebook.com/groups/pythondevelopers/posts/28449935087979081/\" }\n  ],\n  \"maxItems\": 500,\n  \"commentsMode\": \"NEWEST\",\n  \"includeNestedComments\": true,\n  \"maxReplyDepth\": 2,\n  \"onlyCommentsNewerThan\": \"3 months\"\n}\n```\n\n## Output\n\nEach dataset row is one comment or reply.\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `facebookUrl` | string | URL of the post the comment belongs to |\n| `commentUrl` | string | Direct permalink to the comment |\n| `commentId` | string | Numeric (legacy) comment ID |\n| `id` | string | Internal relay ID |\n| `feedbackId` | string | Feedback ID for the comment |\n| `date` | string | Comment timestamp (ISO 8601, UTC) |\n| `text` | string | Full comment text; `[Attachment]` for media-only comments |\n| `profilePicture` | string | Author's profile picture URL |\n| `profileId` | string | Author's numeric or pfbid profile ID |\n| `profileName` | string | Author's display name |\n| `profileUrl` | string | Author's profile URL (when Facebook exposes one) |\n| `likesCount` | integer | Total reactions on the comment |\n| `reactionBreakdown` | object | Per-reaction-type counts (`like`, `love`, `care`, `haha`, `wow`, `sad`, `angry`, `other`); only reaction types with a non-zero count are included |\n| `threadingDepth` | integer | `0` = top-level comment, `1`+ = reply depth |\n| `commentsCount` | integer | Number of replies (0 for replies themselves) |\n| `replyToCommentId` | string | Parent comment's ID; for deep replies where Facebook withholds the direct parent, the thread's top-level comment ID |\n| `directParentCommentId` | string | Facebook's direct parent pointer, when the response includes it |\n| `facebookId` | string | Numeric story/post ID |\n| `inputUrl` | string | The URL exactly as provided in the input |\n| `postTitle` | string | Page name that published the post (kept for integrations) |\n| `pageName` | string | Page name that published the post |\n| `postText` | string | The post's own text (when available) |\n| `postCommentsCount` | integer | Facebook's total comment count for the post |\n| `postVisibleCommentsCount` | integer | Comments Facebook serves to anonymous visitors for the selected ordering |\n| `gender` | string | Author's gender, when Facebook exposes it |\n| `spamDisplayMode` | string | Facebook's own spam classification for the comment |\n| `isDisabled` | boolean | Whether the comment was hidden/removed by moderation |\n| `isHiddenByViewer` | boolean | Whether Facebook hides the comment from anonymous viewers |\n| `attachmentType` | string | `gif`, `sticker`, `image`, `video` or `attachment` for media comments |\n| `attachmentUrl` | string | Media URL for attachment comments — rehosted into Apify's key-value store so it does not expire |\n| `attachmentUrlOriginal` | string | Original signed Facebook CDN URL of the attachment (expires after a few days) |\n| `attachmentUrlExpiresAt` | string | Expiry time of the original signed attachment URL (ISO 8601) |\n| `hashtags` | array | Hashtags used in the comment (without `#`) |\n| `mentions` | array | Profiles mentioned in the comment (without `@`) |\n| `groupCommentInfo` | object | Group posts only: `groupId`, `isAuthorAnonymous`, `isAuthorNickname`, `isAuthorWithMemberProfile` |\n| `groupId` | string | Group ID for group-post comments |\n\n### Example output\n\n```json\n{\n  \"facebookUrl\": \"https://www.facebook.com/NASA/posts/pfbid025kwyoB...\",\n  \"commentUrl\": \"https://www.facebook.com/NASA/posts/pfbid02BnSBZiZ...?comment_id=809453025548580\",\n  \"commentId\": \"809453025548580\",\n  \"id\": \"Y29tbWVudDoxNDg3MDE3OTEyNzkzNTgwXzgwOTQ1MzAyNTU0ODU4MA==\",\n  \"feedbackId\": \"ZmVlZGJhY2s6MTQ4NzAxNzkxMjc5MzU4MF84MDk0NTMwMjU1NDg1ODA=\",\n  \"date\": \"2026-03-26T23:31:17.000Z\",\n  \"text\": \"Ah I remember the moon landing of 1969 on the eve of my 9th birthday!\",\n  \"profileId\": \"pfbid0246xYyRVsKr1v7nDryWNgA4iynY2GKcEVzuVzx2knUikMNEzUNN5RtWsiX945JRt4l\",\n  \"profileName\": \"Gwen Weidell\",\n  \"profileUrl\": \"https://www.facebook.com/gwen.weidell.9\",\n  \"likesCount\": 69,\n  \"reactionBreakdown\": { \"like\": 54, \"haha\": 9, \"love\": 4, \"care\": 1, \"wow\": 1 },\n  \"threadingDepth\": 0,\n  \"commentsCount\": 31,\n  \"facebookId\": \"1487017912793580\",\n  \"inputUrl\": \"https://www.facebook.com/NASA/posts/pfbid025kwyoB...\",\n  \"postTitle\": \"NASA - National Aeronautics and Space Administration\",\n  \"pageName\": \"NASA - National Aeronautics and Space Administration\",\n  \"postText\": \"Our Artemis II crew's journey around the Moon is on the horizon...\",\n  \"postCommentsCount\": 1083,\n  \"postVisibleCommentsCount\": 813,\n  \"gender\": \"FEMALE\",\n  \"spamDisplayMode\": \"none\",\n  \"isDisabled\": false,\n  \"isHiddenByViewer\": false\n}\n```\n\n## Use cases\n\n- **Brand monitoring** — track what people say about your brand across public posts\n- **Market research** — analyze audience sentiment and topics at scale (pipe `text` into your own NLP/LLM step)\n- **Community insights** — understand how audiences react to news, announcements, or campaigns\n- **Competitor analysis** — monitor comment threads on competitor pages and public groups\n- **Lead generation** — identify engaged users from comment activity\n- **Moderation triage** — use Facebook's own spam/disabled/hidden signals plus reply structure to prioritize review\n\n## Tips for best results\n\n1. **Set `maxItems` per URL** — it caps runtime and dataset size; the actor also stops on its own when Facebook runs out of comments\n2. **Use `NEWEST` for fresh-comment monitoring** — with `onlyCommentsNewerThan`, pagination stops as soon as an older comment appears, saving requests\n3. **Keep `includeNestedComments` on** for full threads; turn it off for fast top-level-only exports\n4. **Test with 1–2 URLs first**, then scale up\n5. **Public content only** — posts, photos and groups must be visible without login\n\n## Limitations\n\n- **Some videos are restricted per video**: Facebook serves reel and video comment threads anonymously for most public videos, but a minority return no thread at all; those are reported as \"not served to anonymous visitors\" instead of returning unrelated content (every returned thread is verified against the requested video id).\n- **Anonymous visibility ceiling**: Facebook serves only part of a post's comments to visitors without a session (for example, a post reporting 1,083 comments served 813 to anonymous viewers). The dataset reports what Facebook actually served; `postCommentsCount` vs `postVisibleCommentsCount` shows the difference, and the run status message notes it.\n- **Some photo pages are login-walled from cloud networks**: photo URLs return the photo's own comment thread when it is a standalone photo. When the photo belongs to a post and Facebook blocks the anonymous photo viewer, the actor reports that a logged-in session would be required — paste the post URL that contains the photo to scrape its comments.\n- Some authors have no public profile URL; those rows simply omit `profileUrl`.\n- Attachment media (`attachmentUrl`) is rehosted so it does not expire; original signed URLs stay in `attachmentUrlOriginal`. Profile pictures are Facebook CDN links that expire after a few days (per-row avatars are not rehosted — see FAQ).\n- Private, friends-only, and restricted content cannot be accessed.\n- Occasionally Facebook changes its internal comment API; the actor discovers the current API identifiers at runtime and falls back to the last known ones, but comment ordering and reply visibility are always Facebook's decision.\n\n## FAQ\n\n**Q: Do I need a Facebook account or cookies?**\nA: No. The actor reads public content without any login. Nothing in the input asks for credentials.\n\n**Q: Do I need to configure a proxy?**\nA: No. The actor picks its route automatically, starting with a direct connection and escalating only when Facebook blocks it. There is no proxy input.\n\n**Q: Why are some comments missing?**\nA: Facebook shows anonymous visitors a filtered view of large threads (\"Most relevant\" ordering may hide some comments) and withholds some replies. The actor reports what Facebook serves and never fabricates rows.\n\n**Q: Can I scrape comments from Reels or videos?**\nA: Yes for most public reels and videos — they are followed through Facebook's own canonical video permalink and the returned thread is verified to match the requested video. A minority of videos are restricted by Facebook and return no thread to anonymous visitors; those are reported clearly instead of returning unrelated comments.\n\n**Q: I passed a photo URL and got 0 results. Why?**\nA: Facebook serves some photo pages only to logged-in sessions (this depends on the network the actor runs from). When that happens the actor says so; paste the post URL that contains the photo instead — post URLs are always supported.\n\n**Q: How many comments can I scrape per post?**\nA: Up to `maxItems` (10,000 by default max), and often Facebook's own visibility limit comes first. Exploding threads of thousands of comments are paginated 10 at a time until `maxItems` or Facebook's last page.\n\n**Q: What does `threadingDepth` mean?**\nA: `0` is a top-level comment, `1` is a direct reply, `2`+ is a deeper reply. Use `maxReplyDepth` to control how deep the actor collects.\n\n**Q: Why are profile picture URLs temporary?**\nA: They are signed Facebook CDN links that expire after a few days. Rehosting every row's avatar would dominate run bandwidth, so the actor keeps the CDN link for profile pictures while attachment media (rarer) is rehosted permanently.\n\n**Q: Is this affiliated with Facebook or Meta?**\nA: No. This is an independent, third-party actor that reads publicly accessible comments; it is not affiliated with, endorsed by, or operated by Meta Platforms, Inc.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "facebook-post-and-group-comment-thread-extractor",
      "title": "Facebook Post & Group Comment Thread Extractor",
      "description": "Get comments and nested reply threads from public Facebook posts, photos, and public group posts, with per-reaction-type counts, author details, post totals, and date filtering. No login or cookies required.",
      "version": "1.0",
      "meta": {
        "templateId": "python-start"
      },
      "input": {
        "title": "Facebook Comment Thread Extractor",
        "description": "Extract public comments and reply threads from Facebook posts, photos, reels, videos, and public group posts. Returns comment text, author details, per-reaction-type counts, timestamps, reply context, and the post's own comment totals. No login or cookies required.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "startUrls": {
            "title": "Facebook URLs",
            "type": "array",
            "description": "Facebook post, photo, reel, video, Watch, or public group post URLs (one or more). Comment permalinks (URLs containing ?comment_id=) are accepted and resolved to their post; legacy story.php, permalink.php and share links are normalized automatically. Most public reels and videos are supported; a minority restricted by Facebook return no thread and are reported.",
            "editor": "requestListSources",
            "prefill": [
              {
                "url": "https://www.facebook.com/NASA/posts/pfbid025kwyoBjhFGUC22fC4Sies56D5xvd65ZHR5PYjHhc7XSzqGsxuWq2uDVriZNxWbeol"
              }
            ],
            "sectionCaption": "Input",
            "sectionDescription": "Provide one or more public Facebook URLs to scrape comments from."
          },
          "maxItems": {
            "title": "Max comments per URL",
            "type": "integer",
            "description": "Maximum number of comment rows (including replies) to collect per URL. The run also stops when Facebook has no more comments or replies to serve.",
            "default": 100,
            "prefill": 5,
            "minimum": 1,
            "maximum": 10000,
            "sectionCaption": "Limits"
          },
          "onlyCommentsNewerThan": {
            "title": "Only comments newer than",
            "type": "string",
            "description": "Limit results to comments posted after this date. Accepts YYYY-MM-DD, a full ISO 8601 timestamp (e.g. 2024-06-15T12:00:00Z), or a relative value like '1 day', '2 weeks', '3 months', '1 year'. When set, comments are fetched newest-first so the filter can stop as soon as an older comment is reached. Leave blank to disable date filtering.",
            "editor": "textfield"
          },
          "commentsMode": {
            "title": "Comment ordering",
            "type": "string",
            "description": "Which comment view to scrape: MOST_RELEVANT (Facebook's ranked view), NEWEST (all comments, newest first), or ALL (Facebook's unfiltered ranked view, including comments its ranked view may hide).",
            "enum": [
              "ALL",
              "NEWEST",
              "MOST_RELEVANT"
            ],
            "enumTitles": [
              "All comments (Facebook's unfiltered view)",
              "Newest first",
              "Most relevant (Facebook's ranked view)"
            ],
            "default": "ALL",
            "prefill": "MOST_RELEVANT"
          },
          "includeNestedComments": {
            "title": "Include replies",
            "type": "boolean",
            "description": "If true, also scrape reply rows under top-level comments (with parent/reply metadata). If false, only top-level comments are collected (faster).",
            "default": true,
            "prefill": true
          },
          "maxReplyDepth": {
            "title": "Max reply nesting depth",
            "type": "integer",
            "description": "How deep into reply threads to collect: 1 = direct replies to top-level comments only, 2 or more = also include deeper nested replies. Facebook serves reply threads with up to two nesting levels to anonymous visitors.",
            "default": 1,
            "prefill": 1,
            "minimum": 1,
            "maximum": 5
          }
        },
        "required": [
          "startUrls"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Facebook Post & Group Comment Thread Extractor Output",
        "description": "One record per Facebook comment or reply: text, author details, timestamp, per-reaction-type counts, reply/thread context, attachment and mention data, plus the parent post's name, text and comment totals.",
        "properties": {
          "comments": {
            "type": "string",
            "title": "Comments Data",
            "description": "Dataset containing all scraped Facebook comments",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "defaultRunOptions": {
        "build": "latest",
        "timeoutSecs": 3600,
        "memoryMbytes": 1024
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "title": "Facebook Comments Data",
          "views": {
            "overview": {
              "title": "Comments Overview",
              "transformation": {
                "fields": [
                  "profileName",
                  "text",
                  "date",
                  "likesCount",
                  "commentsCount",
                  "threadingDepth",
                  "commentUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "profileName": {
                    "label": "Author",
                    "format": "text"
                  },
                  "text": {
                    "label": "Comment",
                    "format": "text"
                  },
                  "date": {
                    "label": "Date",
                    "format": "text"
                  },
                  "likesCount": {
                    "label": "Likes",
                    "format": "text"
                  },
                  "commentsCount": {
                    "label": "Replies",
                    "format": "number"
                  },
                  "threadingDepth": {
                    "label": "Depth",
                    "format": "number"
                  },
                  "commentUrl": {
                    "label": "URL",
                    "format": "link"
                  }
                }
              }
            },
            "detailed": {
              "title": "Full Comment Details",
              "transformation": {
                "fields": [
                  "profileName",
                  "profileId",
                  "text",
                  "date",
                  "likesCount",
                  "commentsCount",
                  "threadingDepth",
                  "commentId",
                  "id",
                  "facebookUrl",
                  "commentUrl",
                  "inputUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "profileName": {
                    "label": "Author",
                    "format": "text"
                  },
                  "profileId": {
                    "label": "Profile ID",
                    "format": "text"
                  },
                  "text": {
                    "label": "Comment",
                    "format": "text"
                  },
                  "date": {
                    "label": "Date",
                    "format": "text"
                  },
                  "likesCount": {
                    "label": "Likes",
                    "format": "text"
                  },
                  "commentsCount": {
                    "label": "Replies",
                    "format": "number"
                  },
                  "threadingDepth": {
                    "label": "Depth",
                    "format": "number"
                  },
                  "commentId": {
                    "label": "Comment ID",
                    "format": "text"
                  },
                  "id": {
                    "label": "Relay ID",
                    "format": "text"
                  },
                  "facebookUrl": {
                    "label": "Story URL",
                    "format": "link"
                  },
                  "commentUrl": {
                    "label": "Comment URL",
                    "format": "link"
                  },
                  "inputUrl": {
                    "label": "Input URL",
                    "format": "link"
                  }
                }
              }
            }
          }
        }
      },
      "readme": "# Facebook Post & Group Comment Thread Extractor\n\nGet public comments and full reply threads from Facebook posts, photos, and public group posts. Returns comment text, author details, per-reaction-type counts, timestamps, attachment and mention data, plus the post's own comment totals — no login or cookies required.\n\n## What this actor does\n\n- Scrapes comments from public Facebook posts, photos, reels, videos, and public group posts, with full pagination (thousands of comments per post when Facebook serves them)\n- Reels and videos are followed through Facebook's canonical video permalink, with a strict check that the returned thread belongs to the requested video\n- Follows reply threads and includes nested replies (direct replies plus deeper nesting when Facebook returns it)\n- Three comment orderings: Facebook's ranked view, all comments, or newest first\n- Captures author details (name, profile picture, profile URL, ID), reaction totals and a per-reaction-type breakdown\n- Surfaces the parent post's context on every row: page name, post text, Facebook's total comment count, and the count visible to anonymous visitors\n- Filters results to comments posted after a given date\n- `reactionBreakdown`, `attachmentType`, `hashtags`, `mentions`, `groupCommentInfo` and similar optional fields are only added when Facebook's data carries them\n\n## Input\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `startUrls` | array | – | Required. Facebook post, photo, or public group post URLs. Comment permalinks (`?comment_id=`) are resolved to their post; legacy `story.php`, `permalink.php` and share links are normalized automatically |\n| `maxItems` | integer | `100` | Maximum number of comment rows (including replies) per URL; 1–10,000 |\n| `onlyCommentsNewerThan` | string | – | Date filter: `YYYY-MM-DD`, full ISO 8601, or relative (`1 day`, `2 weeks`, `3 months`, `1 year`). Comments are fetched newest-first so pagination stops early |\n| `commentsMode` | string | `ALL` | Comment ordering: `ALL` (Facebook's unfiltered view), `NEWEST` (newest first), or `MOST_RELEVANT` (Facebook's ranked view) |\n| `includeNestedComments` | boolean | `true` | Also collect reply rows under top-level comments (with parent/reply metadata). Turn off for faster, top-level-only runs |\n| `maxReplyDepth` | integer | `1` | Reply nesting depth to collect: `1` = direct replies only, `2`+ also includes deeper nested replies; 1–5 |\n\nAt least one URL in `startUrls` is required. Provide URLs as plain strings, `{ \"url\": \"...\" }` objects, or several URLs separated by spaces/newlines in one string.\n\n### Supported URL formats\n\n- **Posts**: `https://www.facebook.com/PageName/posts/1234567890`\n- **Posts (pfbid)**: `https://www.facebook.com/PageName/posts/pfbid0...`\n- **Legacy permalinks**: `story.php?story_fbid=...&id=...`, `permalink.php?...` (normalized automatically)\n- **Photos**: `https://www.facebook.com/photo?fbid=1234567890`, `photo.php?fbid=...`, `PageName/photos/...`\n- **Reels**: `https://www.facebook.com/reel/1234567890` (resolved through Facebook's video permalink)\n- **Videos**: `https://www.facebook.com/PageName/videos/1234567890`, `https://www.facebook.com/watch?v=1234567890`\n- **Public group posts**: `https://www.facebook.com/groups/groupname/permalink/1234567890/`, `groups/<id>/posts/<id>`\n- **Comment permalinks**: any post URL with `?comment_id=...` — the parent post's thread is returned\n- **Share links**: `https://www.facebook.com/share/p/...` (resolved through Facebook's redirect)\n- **Mobile URLs**: `m.facebook.com/...` links are normalized to `www`\n\nSome individual videos are restricted by Facebook and do not expose their comment thread to anonymous visitors; the actor reports that per video instead of guessing (see Limitations).\n\n### Example input\n\n```json\n{\n  \"startUrls\": [\n    { \"url\": \"https://www.facebook.com/NASA/posts/1234567890\" },\n    { \"url\": \"https://www.facebook.com/groups/pythondevelopers/posts/28449935087979081/\" }\n  ],\n  \"maxItems\": 500,\n  \"commentsMode\": \"NEWEST\",\n  \"includeNestedComments\": true,\n  \"maxReplyDepth\": 2,\n  \"onlyCommentsNewerThan\": \"3 months\"\n}\n```\n\n## Output\n\nEach dataset row is one comment or reply.\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `facebookUrl` | string | URL of the post the comment belongs to |\n| `commentUrl` | string | Direct permalink to the comment |\n| `commentId` | string | Numeric (legacy) comment ID |\n| `id` | string | Internal relay ID |\n| `feedbackId` | string | Feedback ID for the comment |\n| `date` | string | Comment timestamp (ISO 8601, UTC) |\n| `text` | string | Full comment text; `[Attachment]` for media-only comments |\n| `profilePicture` | string | Author's profile picture URL |\n| `profileId` | string | Author's numeric or pfbid profile ID |\n| `profileName` | string | Author's display name |\n| `profileUrl` | string | Author's profile URL (when Facebook exposes one) |\n| `likesCount` | integer | Total reactions on the comment |\n| `reactionBreakdown` | object | Per-reaction-type counts (`like`, `love`, `care`, `haha`, `wow`, `sad`, `angry`, `other`); only reaction types with a non-zero count are included |\n| `threadingDepth` | integer | `0` = top-level comment, `1`+ = reply depth |\n| `commentsCount` | integer | Number of replies (0 for replies themselves) |\n| `replyToCommentId` | string | Parent comment's ID; for deep replies where Facebook withholds the direct parent, the thread's top-level comment ID |\n| `directParentCommentId` | string | Facebook's direct parent pointer, when the response includes it |\n| `facebookId` | string | Numeric story/post ID |\n| `inputUrl` | string | The URL exactly as provided in the input |\n| `postTitle` | string | Page name that published the post (kept for integrations) |\n| `pageName` | string | Page name that published the post |\n| `postText` | string | The post's own text (when available) |\n| `postCommentsCount` | integer | Facebook's total comment count for the post |\n| `postVisibleCommentsCount` | integer | Comments Facebook serves to anonymous visitors for the selected ordering |\n| `gender` | string | Author's gender, when Facebook exposes it |\n| `spamDisplayMode` | string | Facebook's own spam classification for the comment |\n| `isDisabled` | boolean | Whether the comment was hidden/removed by moderation |\n| `isHiddenByViewer` | boolean | Whether Facebook hides the comment from anonymous viewers |\n| `attachmentType` | string | `gif`, `sticker`, `image`, `video` or `attachment` for media comments |\n| `attachmentUrl` | string | Media URL for attachment comments — rehosted into Apify's key-value store so it does not expire |\n| `attachmentUrlOriginal` | string | Original signed Facebook CDN URL of the attachment (expires after a few days) |\n| `attachmentUrlExpiresAt` | string | Expiry time of the original signed attachment URL (ISO 8601) |\n| `hashtags` | array | Hashtags used in the comment (without `#`) |\n| `mentions` | array | Profiles mentioned in the comment (without `@`) |\n| `groupCommentInfo` | object | Group posts only: `groupId`, `isAuthorAnonymous`, `isAuthorNickname`, `isAuthorWithMemberProfile` |\n| `groupId` | string | Group ID for group-post comments |\n\n### Example output\n\n```json\n{\n  \"facebookUrl\": \"https://www.facebook.com/NASA/posts/pfbid025kwyoB...\",\n  \"commentUrl\": \"https://www.facebook.com/NASA/posts/pfbid02BnSBZiZ...?comment_id=809453025548580\",\n  \"commentId\": \"809453025548580\",\n  \"id\": \"Y29tbWVudDoxNDg3MDE3OTEyNzkzNTgwXzgwOTQ1MzAyNTU0ODU4MA==\",\n  \"feedbackId\": \"ZmVlZGJhY2s6MTQ4NzAxNzkxMjc5MzU4MF84MDk0NTMwMjU1NDg1ODA=\",\n  \"date\": \"2026-03-26T23:31:17.000Z\",\n  \"text\": \"Ah I remember the moon landing of 1969 on the eve of my 9th birthday!\",\n  \"profileId\": \"pfbid0246xYyRVsKr1v7nDryWNgA4iynY2GKcEVzuVzx2knUikMNEzUNN5RtWsiX945JRt4l\",\n  \"profileName\": \"Gwen Weidell\",\n  \"profileUrl\": \"https://www.facebook.com/gwen.weidell.9\",\n  \"likesCount\": 69,\n  \"reactionBreakdown\": { \"like\": 54, \"haha\": 9, \"love\": 4, \"care\": 1, \"wow\": 1 },\n  \"threadingDepth\": 0,\n  \"commentsCount\": 31,\n  \"facebookId\": \"1487017912793580\",\n  \"inputUrl\": \"https://www.facebook.com/NASA/posts/pfbid025kwyoB...\",\n  \"postTitle\": \"NASA - National Aeronautics and Space Administration\",\n  \"pageName\": \"NASA - National Aeronautics and Space Administration\",\n  \"postText\": \"Our Artemis II crew's journey around the Moon is on the horizon...\",\n  \"postCommentsCount\": 1083,\n  \"postVisibleCommentsCount\": 813,\n  \"gender\": \"FEMALE\",\n  \"spamDisplayMode\": \"none\",\n  \"isDisabled\": false,\n  \"isHiddenByViewer\": false\n}\n```\n\n## Use cases\n\n- **Brand monitoring** — track what people say about your brand across public posts\n- **Market research** — analyze audience sentiment and topics at scale (pipe `text` into your own NLP/LLM step)\n- **Community insights** — understand how audiences react to news, announcements, or campaigns\n- **Competitor analysis** — monitor comment threads on competitor pages and public groups\n- **Lead generation** — identify engaged users from comment activity\n- **Moderation triage** — use Facebook's own spam/disabled/hidden signals plus reply structure to prioritize review\n\n## Tips for best results\n\n1. **Set `maxItems` per URL** — it caps runtime and dataset size; the actor also stops on its own when Facebook runs out of comments\n2. **Use `NEWEST` for fresh-comment monitoring** — with `onlyCommentsNewerThan`, pagination stops as soon as an older comment appears, saving requests\n3. **Keep `includeNestedComments` on** for full threads; turn it off for fast top-level-only exports\n4. **Test with 1–2 URLs first**, then scale up\n5. **Public content only** — posts, photos and groups must be visible without login\n\n## Limitations\n\n- **Some videos are restricted per video**: Facebook serves reel and video comment threads anonymously for most public videos, but a minority return no thread at all; those are reported as \"not served to anonymous visitors\" instead of returning unrelated content (every returned thread is verified against the requested video id).\n- **Anonymous visibility ceiling**: Facebook serves only part of a post's comments to visitors without a session (for example, a post reporting 1,083 comments served 813 to anonymous viewers). The dataset reports what Facebook actually served; `postCommentsCount` vs `postVisibleCommentsCount` shows the difference, and the run status message notes it.\n- **Some photo pages are login-walled from cloud networks**: photo URLs return the photo's own comment thread when it is a standalone photo. When the photo belongs to a post and Facebook blocks the anonymous photo viewer, the actor reports that a logged-in session would be required — paste the post URL that contains the photo to scrape its comments.\n- Some authors have no public profile URL; those rows simply omit `profileUrl`.\n- Attachment media (`attachmentUrl`) is rehosted so it does not expire; original signed URLs stay in `attachmentUrlOriginal`. Profile pictures are Facebook CDN links that expire after a few days (per-row avatars are not rehosted — see FAQ).\n- Private, friends-only, and restricted content cannot be accessed.\n- Occasionally Facebook changes its internal comment API; the actor discovers the current API identifiers at runtime and falls back to the last known ones, but comment ordering and reply visibility are always Facebook's decision.\n\n## FAQ\n\n**Q: Do I need a Facebook account or cookies?**\nA: No. The actor reads public content without any login. Nothing in the input asks for credentials.\n\n**Q: Do I need to configure a proxy?**\nA: No. The actor picks its route automatically, starting with a direct connection and escalating only when Facebook blocks it. There is no proxy input.\n\n**Q: Why are some comments missing?**\nA: Facebook shows anonymous visitors a filtered view of large threads (\"Most relevant\" ordering may hide some comments) and withholds some replies. The actor reports what Facebook serves and never fabricates rows.\n\n**Q: Can I scrape comments from Reels or videos?**\nA: Yes for most public reels and videos — they are followed through Facebook's own canonical video permalink and the returned thread is verified to match the requested video. A minority of videos are restricted by Facebook and return no thread to anonymous visitors; those are reported clearly instead of returning unrelated comments.\n\n**Q: I passed a photo URL and got 0 results. Why?**\nA: Facebook serves some photo pages only to logged-in sessions (this depends on the network the actor runs from). When that happens the actor says so; paste the post URL that contains the photo instead — post URLs are always supported.\n\n**Q: How many comments can I scrape per post?**\nA: Up to `maxItems` (10,000 by default max), and often Facebook's own visibility limit comes first. Exploding threads of thousands of comments are paginated 10 at a time until `maxItems` or Facebook's last page.\n\n**Q: What does `threadingDepth` mean?**\nA: `0` is a top-level comment, `1` is a direct reply, `2`+ is a deeper reply. Use `maxReplyDepth` to control how deep the actor collects.\n\n**Q: Why are profile picture URLs temporary?**\nA: They are signed Facebook CDN links that expire after a few days. Rehosting every row's avatar would dominate run bandwidth, so the actor keeps the CDN link for profile pictures while attachment media (rarer) is rehosted permanently.\n\n**Q: Is this affiliated with Facebook or Meta?**\nA: No. This is an independent, third-party actor that reads publicly accessible comments; it is not affiliated with, endorsed by, or operated by Meta Platforms, Inc.\n"
    },
    "buildNumber": "1.0.2",
    "imageDigest": "2c1ae6decf606e9c9955617f2d34eeb6044289e069a291d0c3f8e6431852faf0",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "1.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.014564444444444444
    }
  }
}