SocialCrawl

Metric substitutions and structural nulls

Where a platform's upstream cannot supply a canonical field, SocialCrawl returns an honest null rather than a fabricated value or a substituted metric. This page lists every structural null by platform.

Metric substitutions and structural nulls

SocialCrawl maps 48 platforms onto one canonical schema. Not every platform exposes every canonical field. When an upstream cannot supply a field, we follow one rule: return an honest null, never a fabricated value, and never a different metric wearing the field's name. Where a platform exposes a closely-related metric worth having, it goes under an ext.* namespace so the canonical leaf keeps meaning exactly what it says.

This page is the source of truth for those cases. If a field is listed here as a structural null for a platform, its absence is by upstream design, not a bug.

For how the derived computed block (engagement_rate, language, content_category, estimated_reach) is calculated, see Computed fields.

Metric substitutions

There are currently no metric substitutions anywhere in the API. Every canonical field holds the metric its name implies, or null. Where a platform exposes a closely-related metric that does not fit a canonical slot, it is namespaced under ext.* rather than folded into the nearest-looking leaf — see the Spotify entry below for the one case that used to work the other way.

Structural nulls by platform

These canonical fields are null across a platform's surfaces because the upstream never exposes them. They will not populate no matter how you call the endpoint.

Instagram

  • post.engagement.saves is always null. Instagram exposes only a per-viewer viewer_has_saved boolean, never an aggregate count. This is platform-private.
  • post.engagement.shares is null on the base endpoints. A reshare count is only available on post/stats and the *-full composites (instagram/profile/reels/full, instagram/profile/posts/full), which pull the mobile reshare_count. Read shares from those surfaces.
  • post.engagement.views (and the shares count above) exist only on video media: reels, videos, and carousels containing a video. Photo posts and photo-only carousels have no public view or share count on Instagram, so both fields are null there on every endpoint, and the views-derived computed.engagement_rate and computed.estimated_reach are null with them. Likes and comments populate on every media type.
  • Stories carry no engagement metrics at all. Story views, replies, likes, and reach are owner-only analytics Instagram exposes to no third party. /v1/instagram/stories returns each active story's media, timestamps, and IDs with the engagement leaves null; no API from any provider can return story metrics or story reach for an account you don't own.

YouTube

  • post.engagement.shares and post.engagement.saves are null. Both are owner-only analytics upstream.

Reddit

  • post.engagement.views, post.engagement.shares, and post.engagement.saves are null. Reddit does not expose view or share counts, and "saved" is a per-viewer flag upstream, never a count.
  • author.verified is null (not exposed).

Facebook

  • post.engagement.saves is null (not exposed).
  • On list surfaces, list-item author.avatar_url and post.media_urls can be null because the list-item shape is slimmer than the single-object shape.

Naver's Search corpora (blog, news, cafe, book, webkr, image, kin, shop, doc, encyc) are search indexes, not social feeds, so:

  • post.engagement.views, post.engagement.likes, and post.engagement.comments are null on every Naver Search corpus. There are no engagement signals to return.
  • author.avatar_url, post.media_urls, and post.published_at vary by corpus and are null on the corpora that do not carry them (for example news and image differ from blog).

Spotify

  • author.posts_count is null for artists. Spotify artists have no posts. The headline reach metric is surfaced separately as author.ext.monthly_listeners — it is not folded into posts_count, because a listener figure sitting in a "number of posts" leaf corrupts any cross-platform posts aggregate.
  • author.following, author.likes_count, and author.verified are null for artists (not exposed upstream).
  • Album, track, and podcast rows carry no post.engagement.*.

Google Finance

  • quote.price.previous_close is null when the upstream quote omits it. It is a structural null, not a fixed value. It can be derived client-side from the current price and change when you need it.

Google Shopping

  • product.brand is null. Google Shopping does not return a clean brand field. Only Amazon products carry a populated brand. If you need the brand for a Shopping product, it can often be lifted from product.specifications[].

Other platforms

  • Rumble: search (SERP) rows carry no post.engagement.*, author.avatar_url, or post.published_at.
  • Threads: slim search-user rows omit author.avatar_url, author.bio, and author.followers.
  • Twitter/X: the single-tweet shape carries no post.pinned flag; it defaults to false.
  • GitHub: author.avatar_url is null on several archetypes, and there is no like primitive so post.engagement.likes is null.
  • TikTok: root comments carry no post.parent_id by design (only replies do).
  • Google Business: business/updates rows carry no author.username.

Changed defaults

Two endpoints apply a SocialCrawl-chosen default when you omit a sort/type parameter, so results are predictable:

  • google_play/app-reviews (and app_store/app-reviews) default sort_by to newest-first when you omit it. Google Play's own upstream default is "most relevant"; we override it so an unspecified sort returns the newest reviews. The per-store value is newest for Google Play and most_recent for the App Store. Passing an explicit sort_by always wins.
  • instagram/search/hashtag defaults type to top when you omit it. Pass type=recent or type=clips to change it.