# Comment schema (/docs/schema/comment) The unified SocialCrawl comment schema. Every field, its type, per-platform availability, and a machine-readable JSON Schema, generated from the canonical Zod source. Every SocialCrawl endpoint that returns a comment gives you this exact shape, whatever the source platform. Write your parser once and the same code reads comment data from every platform below. That is the unified schema: one contract instead of a dozen raw upstream formats. ## Field reference | Field | Type | Nullable | Description | | ----- | ---- | -------- | ----------- | | `id` | `string` | No | Platform-specific comment ID (always a string) | | `url` | `string` | Yes | Direct URL to the comment on the source platform | | `parent_id` | `string` | Yes | Parent comment ID for nested replies, or null for top-level comments | | `post_id` | `string` | Yes | ID of the post this comment belongs to | | `text` | `string` | Yes | Comment body. Tombstone sentinels ([deleted] / [removed]) are collapsed to null upstream: customers never see them. | | `author.username` | `string` | Yes | Comment author username (null when tombstoned) | | `author.display_name` | `string` | Yes | Comment author display name | | `author.avatar_url` | `string` | Yes | URL to comment author profile picture | | `author.verified` | `boolean` | Yes | Whether the comment author is verified | | `engagement.likes` | `integer` | Yes | Like / upvote count | | `engagement.replies` | `integer` | Yes | Reply / child-comment count. `0` when the upstream structurally reports the count and the comment has no replies; `null` only when the upstream does not surface a reply count at all. | | `flags.pinned` | `boolean` | Yes | Pinned flag (null when platform does not surface) | | `flags.deleted` | `boolean` | No | Whether the comment is tombstoned (always present, even when false) | | `published_at` | `string` or `integer` | Yes | Comment creation timestamp as an ISO 8601 UTC string. When the upstream sent a Unix epoch it is converted here and the raw epoch is preserved under `comment.ext.published_at_epoch` for one deprecation cycle. | | `replies` | `object[]` | Yes | Nested reply tree: array of child comments, each itself a full Comment object with its own `replies`. Populated on threaded platforms (Reddit); absent on flat-comment platforms, which thread only via `parent_id`. | ## Extension fields (`ext`) Platform-specific passthrough. Each field is present only on the platforms that expose it and is absent everywhere else, so treat every `ext.*` field as optional. These carry the richer, per-platform signals the unified leaves cannot hold, and the join keys that chain endpoints together. | Field | Type | Nullable | Description | | ----- | ---- | -------- | ----------- | | `ext.replies_token` | `string` | Yes | YouTube reply continuation token: pass to `/v1/youtube/video/comment/replies?continuationToken=` | | `ext.replies_cursor` | `string` | Yes | Reddit reply-branch continuation cursor. Present when this comment's reply tree is truncated upstream: pass it back as `?cursor=` on `/v1/reddit/post/comments` to load the rest of the branch. | | `ext.depth` | `integer` | Yes | Reddit comment nesting depth as the source reports it: 0 on a top-level comment, 1 on a direct reply, and so on. Present when the thread arrived flat and was re-nested into `replies[]`, so you can verify that nesting independently. | | `ext.published_at_epoch` | `integer` | Yes | Raw Unix epoch for `published_at` (present only when the upstream sent a numeric epoch that was normalised to the ISO 8601 string). | | `ext.feedback_id` | `string` | Yes | Facebook comment feedback id: feeds `/v1/facebook/post/comment/replies` | | `ext.expansion_token` | `string` | Yes | Facebook comment expansion/paginator token: feeds `/v1/facebook/post/comment/replies` | | `ext.author_id` | `string` | Yes | The commenter's platform-native numeric user id, where the upstream exposes one. | | `ext.urn` | `string` | Yes | | | `ext.reaction_counts` | `string[]` | Yes | | | `ext.is_edited` | `boolean` | Yes | | | `ext.previous_replies_token` | `string` | Yes | | | `ext.author_headline` | `string` | Yes | | | `ext.updated_at` | `string` | Yes | | | `ext.author_channel_id` | `string` | Yes | | | `ext.author_url` | `string` | Yes | | | `ext.viewer_rating` | `string` | Yes | | | `ext.text_original` | `string` | Yes | | | `ext.preview_replies` | `string[]` | Yes | | | `ext.lookup` | `string` | Yes | | | `ext.post_title` | `string` | Yes | | | `ext.post_url` | `string` | Yes | | | `ext.subreddit` | `string` | Yes | | | `ext.subreddit_subscribers` | `integer` | Yes | | | `ext.post_score` | `integer` | Yes | | | `ext.post_comment_count` | `integer` | Yes | | | `ext.post_author` | `string` | Yes | | | `ext.post_published_at` | `string` | Yes | | | `ext.post_flair` | `string` | Yes | | | `ext.is_submitter` | `boolean` | Yes | | | `ext.edited_at` | `string` | Yes | | | `ext.controversiality` | `integer` | Yes | | | `ext.content_language` | `string` | Yes | ISO 639-1 language tag for this comment, when the source reports one. X writes `zxx` / `und` for no linguistic content; those collapse to null. | | `ext.author_followers` | `integer` | Yes | The commenter's follower count as embedded in this row. Snapshot as of whenever the replies source saw the account, not a live figure. On X this is present on every `tweet/replies` row. | | `ext.author_following` | `integer` | Yes | The commenter's following count as embedded in this row. Same snapshot caveat as `author_followers`. | | `ext.author_posts_count` | `integer` | Yes | The commenter's post count as embedded in this row. Same snapshot caveat as `author_followers`. | | `ext.quote_count` | `integer` | Yes | How many quote-posts this comment has, when the source reports it. On X a reply is a tweet, so this is the same figure `post.ext.quote_count` carries on tweet lanes. | | `ext.views` | `integer` | Yes | View count for this comment, when the source reports it. On X a reply is a tweet and the count is public on posts from ~2022 onward. | | `ext.saves` | `integer` | Yes | Bookmark / save count for this comment, when the source reports it. On X this is `legacy.bookmark_count`. | ## Platform availability 14 platforms return the `Comment` shape. `id`, `flags.deleted` are never null on any platform. The fields below vary: **yes** means the platform populates it (the value may still be null); a blank means the platform never provides it, so it is always null.
| Platform | `parent_id` | `author.verified` | `flags.pinned` | `url` | `post_id` | `author.avatar_url` | `author.display_name` | `engagement.replies` | `author.username` | `engagement.likes` | | -------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Douyin | yes | yes | | | yes | yes | yes | yes | yes | yes | | Facebook | | | | | | yes | yes | yes | yes | yes | | GitHub | | | | yes | yes | yes | | | yes | yes | | Google | yes | | | yes | yes | yes | yes | yes | yes | | | Hacker News | yes | | | | yes | | | | yes | yes | | Instagram | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | LinkedIn | | | yes | | | | yes | yes | | | | Reddit | yes | yes | yes | yes | yes | yes | yes | | yes | yes | | Rumble | | | | | | yes | yes | yes | yes | yes | | Snapchat | | | | | yes | | yes | yes | | yes | | Threads | | yes | yes | | | yes | yes | yes | yes | yes | | TikTok | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | Twitter/X | yes | yes | | | yes | yes | yes | yes | yes | yes | | YouTube | | | | | yes | yes | | yes | yes | yes |
## Machine-readable schema Validate responses programmatically against the JSON Schema (2020-12): [`/schemas/comment.json`](/schemas/comment.json) Point a validator (Ajv, `jsonschema`, or your framework's) at that URL, or hand it to an agent so it can check the shape without a live call. ## Returned by Endpoints with the `Comment` / `CommentList` archetype return this shape: [Douyin](/platforms/douyin) · [Facebook](/platforms/facebook) · [GitHub](/platforms/github) · [Google](/platforms/google) · [Hacker News](/platforms/hackernews) · [Instagram](/platforms/instagram) · [LinkedIn](/platforms/linkedin) · [Reddit](/platforms/reddit) · [Rumble](/platforms/rumble) · [Snapchat](/platforms/snapchat) · [Threads](/platforms/threads) · [TikTok](/platforms/tiktok) · [Twitter/X](/platforms/twitter) · [YouTube](/platforms/youtube) See how the same fields map to each platform's raw upstream names in the [cross-platform field equivalence table](/docs/schema/field-equivalence.md).