Lemon8 Profile Scraper: Posts, Engagement, Comments & Media
Pricing
from $2.00 / 1,000 results
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
Maintained by CommunityActor stats
0
Bookmarked
55
Total users
11
Monthly active users
4 days ago
Last modified
Categories
Share
Lemon8 Profile Scraper

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 withincrementalModeto get only NEW/UPDATED/REAPPEARED/EXPIRED posts instead of a full re-scrape every time
Input Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
username | string | required | Lemon8 username (without @) |
profileUrl | string | - | Full profile URL (alternative to username) |
region | string | "us" | Region code |
limit | int | 100 | Max posts to extract |
getDetails | bool | true | Extract full post details |
detailsLimit | int | 10 | Max posts for detail extraction |
saveImages | bool | false | Download images to KVS |
saveVideos | bool | false | Download videos to KVS |
getFollowing | bool | false | Extract following profiles |
followingLimit | int | 20 | Max following profiles to extract |
proxy | object | null | Proxy configuration |
resumeFromRunId | string | - | Previous run/dataset ID to continue an interrupted pull without re-returning (or re-charging for) posts already collected there |
incrementalMode | bool | false | Recurring monitoring: remembers the previous run's posts itself and returns only NEW/UPDATED/REAPPEARED posts (plus UNCHANGED/EXPIRED if enabled below) |
stateKey | string | - | Incremental mode only: name the monitoring campaign explicitly; otherwise derived from username/Profile URL/Start URLs + region + getDetails |
emitUnchanged | bool | false | Incremental mode only: also return (and bill) posts unchanged since the last run, marked UNCHANGED |
emitExpired | bool | false | Incremental 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, andgetDetails) and classifies every post asNEW,UPDATED,UNCHANGED,REAPPEARED, orEXPIREDagainst the previous run. Each dataset row gainschangeType,changedFields,firstSeenAt, andlastSeenAtfields.UNCHANGEDposts are suppressed (not returned or billed) unlessemitUnchangedis on;EXPIREDposts are only ever produced whenemitExpiredis 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 staysUNCHANGED; 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.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto 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 existingpostsCount, which reflects only the first fetched page of posts, not the profile total;postsCountis left exactly as it was.userInfo.socialLinksDetailed: the same social accounts associalLinks, but withplatformand the actual clickableurlincluded (the existingsocialLinkslist of names is unchanged).posts[].details.publishedAt: the post's original publish time (full UTC timestamp), distinct from the existingeditTime, 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 (includingEXPIREDtombstones), 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.