Lemon8 Profile Scraper: Posts, Engagement, Comments & Media avatar

Lemon8 Profile Scraper: Posts, Engagement, Comments & Media

Pricing

from $2.00 / 1,000 results

Go to Apify Store
Lemon8 Profile Scraper: Posts, Engagement, Comments & Media

Lemon8 Profile Scraper: Posts, Engagement, Comments & Media

Scrape Lemon8 user profiles with automated multi-profile discovery. Extract profile data, detailed posts, engagement metrics, comments, and high-quality images and videos with download support. Built for influencer research, content analysis, and media archiving.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

55

Total users

11

Monthly active users

4 days ago

Last modified

Share

Lemon8 Profile Scraper

Lemon8 Scraper Banner

Scrape Lemon8 user profiles with support for automated multi-profile discovery. Extract detailed posts, engagement stats, comments, and download high-quality images and videos. Ideal for data analysis, media archiving, and influencer research.

Features

  • Profile Scraping - Extract user info, bio, stats, social links
  • Post Extraction - Scrape posts with infinite scroll support
  • Full Post Data - Titles, content, statistics, hashtags
  • Comment Extraction - All comments including replies (with "See more" expansion)
  • Video Detection - Identify and extract video post data
  • Media Downloads - Save images and videos to Key-Value Store
  • Following Profiles - Extract list of followed users
  • 10+ Regions - Support for US, Australia, Japan, and more
  • Reliable Access - Smart proxy rotation with automatic fallback
  • Apify Compatible - Stable, well-defined input/output schema
  • Resume & Incremental Updates - Continue an interrupted pull with resumeFromRunId, or schedule recurring runs with incrementalMode to get only NEW/UPDATED/REAPPEARED/EXPIRED posts instead of a full re-scrape every time

Input Configuration

ParameterTypeDefaultDescription
usernamestringrequiredLemon8 username (without @)
profileUrlstring-Full profile URL (alternative to username)
regionstring"us"Region code
limitint100Max posts to extract
getDetailsbooltrueExtract full post details
detailsLimitint10Max posts for detail extraction
saveImagesboolfalseDownload images to KVS
saveVideosboolfalseDownload videos to KVS
getFollowingboolfalseExtract following profiles
followingLimitint20Max following profiles to extract
proxyobjectnullProxy configuration
resumeFromRunIdstring-Previous run/dataset ID to continue an interrupted pull without re-returning (or re-charging for) posts already collected there
incrementalModeboolfalseRecurring monitoring: remembers the previous run's posts itself and returns only NEW/UPDATED/REAPPEARED posts (plus UNCHANGED/EXPIRED if enabled below)
stateKeystring-Incremental mode only: name the monitoring campaign explicitly; otherwise derived from username/Profile URL/Start URLs + region + getDetails
emitUnchangedboolfalseIncremental mode only: also return (and bill) posts unchanged since the last run, marked UNCHANGED
emitExpiredboolfalseIncremental mode only: also return (and bill) posts no longer found, marked EXPIRED — only once a run fully scans every tracked profile

Resume & recurring updates

Two distinct features, both off by default:

  • Resume (resumeFromRunId) continues ONE specific interrupted run — paste the previous run ID or dataset ID and this run skips posts already collected there.
  • Incremental mode (incrementalMode) is for scheduling this actor on the same profile(s) again and again (e.g. daily). It keeps its own state (keyed by username/Profile URL/Start URLs, region, and getDetails) and classifies every post as NEW, UPDATED, UNCHANGED, REAPPEARED, or EXPIRED against the previous run. Each dataset row gains changeType, changedFields, firstSeenAt, and lastSeenAt fields. UNCHANGED posts are suppressed (not returned or billed) unless emitUnchanged is on; EXPIRED posts are only ever produced when emitExpired is on and the run fully scanned every tracked profile (not capped by Post Limit, not a resumed run). Note that the post's view counter (details.statistics.viewsCount) and the per-run media re-upload URLs are excluded from change detection, so a post whose view count alone moved stays UNCHANGED; the current value is still on every returned row.

Both fields live in the Resume & recurring updates input section — normal (non-incremental) runs are completely unaffected and never see these extra fields.

Example Input

{
"username": "sample_creator123",
"region": "us",
"limit": 50,
"getDetails": true,
"detailsLimit": 10,
"saveImages": false,
"saveVideos": false,
"getFollowing": false,
"followingLimit": 20
}

Regions

us, au, nz, jp, th, id, vn, my, sg, ca

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape — the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record — not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Output Format

Each dataset row is a post (shape below). In incremental mode only, every row also carries changeType (NEW/UPDATED/UNCHANGED/REAPPEARED/EXPIRED), changedFields, firstSeenAt, and lastSeenAt — see Resume & recurring updates above. These fields never appear on a normal (non-incremental) run.

Every value in the sample below (account name, username, social handles and links, post text, ids, counts, timestamps) is a fictional placeholder used purely to show the shape of the output. It is not taken from any real Lemon8 account.

{
"userInfo": {
"name": "Sample Creator",
"bio": "sample profile bio...",
"followers": "12.3K",
"following": "87",
"likesAndSaves": "45.6K",
"profileImageUrl": "https://...",
"profileUrl": "/@sample_creator123",
"socialLinks": ["sample_creator_ig"],
"userId": "1234567890123456789",
"isVerified": false,
"totalPosts": 120,
"socialLinksDetailed": [
{"platform": "ins", "name": "sample_creator_ig", "url": "https://www.instagram.com/sample_creator_ig/"}
]
},
"posts": [
{
"id": "7000000000000000001",
"author": {
"name": "Sample Creator",
"profileUrl": "/@sample_creator123",
"profileImageUrl": "https://...",
"userId": "1234567890123456789"
},
"title": "Sample post title",
"content": "The post body text appears here...",
"postUrl": "https://...",
"statistics": {
"savedCount": "120",
"likesCount": "450",
"commentsCount": "12"
},
"images": [...],
"isVideo": false,
"details": {
"fullContent": "...",
"hashtags": ["#sampletag", ...],
"publishedAt": "2025-01-15T09:30:00Z",
"statistics": {
"savedCount": "8",
"likesCount": "31",
"commentsCount": "2",
"viewsCount": "1500"
},
"videoData": {...}
},
"allComments": [
{"author": "Sample Commenter", "content": "Sample comment text", "commentId": "7000000000000000002"}
],
"commentStats": {
"totalComments": 12,
"totalReplies": 4
}
}
],
"following": [
{"username": "sample_following_user", "name": "Sample Following User", "userId": "9876543210987654321"}
],
"metadata": {
"profileUrl": "https://...",
"username": "sample_creator123",
"region": "us",
"totalScraped": 50,
"scrollsPerformed": 15,
"videoPostsFound": 5,
"detailedPostsScraped": 10,
"followingProfilesScraped": 0
}
}

Additional fields (feature-parity pass)

These fields were confirmed available on the live site but were previously dropped by this actor, and have now been added. All of them are purely additive: no existing field changed name, type, or meaning, and no existing input default changed.

  • userInfo.userId, posts[].author.userId, following[].userId: the stable numeric account id the site itself uses, so a profile, a post's author, and a followed account can be joined or deduplicated by id instead of by display name.
  • userInfo.isVerified: the verification badge shown next to the display name on the live profile page.
  • userInfo.totalPosts: the profile's total post count as the site reports it. Note this is a separate field from the existing postsCount, which reflects only the first fetched page of posts, not the profile total; postsCount is left exactly as it was.
  • userInfo.socialLinksDetailed: the same social accounts as socialLinks, but with platform and the actual clickable url included (the existing socialLinks list of names is unchanged).
  • posts[].details.publishedAt: the post's original publish time (full UTC timestamp), distinct from the existing editTime, which reflects the last edit and drops the year.
  • posts[].details.statistics.viewsCount: the view counter shown on the live post page alongside likes, saves, and comments. Always present on every returned row (including EXPIRED tombstones), but deliberately not part of incremental change detection, see the note below.
  • posts[].allComments[].commentId / comments[].commentId: a stable id for each comment, for deduplication or joining across runs.

What this means for incremental mode (incrementalMode)

details.statistics.viewsCount is a live engagement counter that keeps ticking up on its own, so it is excluded from the change fingerprint: a post whose view count is the only thing that moved between two scheduled runs stays UNCHANGED and is not returned or billed again. UPDATED therefore means the post's own content or its other tracked fields changed, not that more people viewed it. The value itself is never dropped, every returned row still carries the current view count. If you are monitoring view counts specifically, turn on emitUnchanged to get every tracked post back on every run and read details.statistics.viewsCount from the row.

details.publishedAt is different: it is a stable one-time value, so it does participate in the fingerprint. Because it is new, the first run after this update will see every already-tracked post's changedFields gain details once and reclassify from UNCHANGED to UPDATED. That is a one-time re-baseline caused by the new field appearing, not a real content change, and it does not repeat on later runs.