# Lemon8 Scraper: Profiles, Posts, Hashtags, Keywords, Comments (`neverempty/lemon8-scraper-all-in-one`) Actor

For influencer research, trend tracking and brand monitoring: Lemon8 profiles and posts with views, saves, likes, comments, hashtags and images, by profile, keyword, hashtag or 22 category feeds in 12 markets. Saves image and video copies. Monitoring flags new, changed and deleted posts. No login.

- **URL**: https://apify.com/neverempty/lemon8-scraper-all-in-one.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Marketing, Videos
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.49 / 1,000 post returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Lemon8 Scraper: Profiles, Posts, Hashtags, Keywords, Comments

**Export Lemon8 posts and creator profiles to JSON, CSV or Excel for influencer research, trend tracking and brand monitoring: every post with views, saves, likes, comment count, full text, hashtags, all images, the video link and publish date, plus creator followers, likes and saves received.** Start from creator profiles, post links, keywords, hashtags or any of 22 category feeds in 12 Lemon8 markets, all in one run, with no login.

- **Find creators in your niche.** Search a keyword or hashtag and each post carries its creator's username and follower count; add the profile to get bio, links, post count and likes and saves received.
- **Full engagement on every post.** Views, saves, likes, comment count, publish date, full text, every image and the video link (`includePostDetails`, on by default).
- **Images and videos that stay available.** Lemon8 image links expire after about 7 days. Turn on `saveImages` / `saveVideos` and each post's images and video are copied to a named store in your Apify account, with permanent links in `savedImageUrls` and `savedVideoUrl`.
- **See what changed since the last run.** Schedule it in monitoring mode and each run returns only posts marked `NEW`, `UPDATED` (likes, saves, comments or text changed, with the previous values) or `EXPIRED` (deleted from the profile).
- **Comments as rows.** `includeComments` adds each post's comments: text, likes, reply count, date, commenter display name, and whether the creator wrote it.
- **Whole profiles and wide keywords.** A creator's posts come newest first until `maxItems`. A keyword continues with the hashtag of the same name and the searches Lemon8 suggests ("skincare" -> "skincare routine"), each marked in `source`.

### Who uses it

- **Influencer marketing**: shortlist Lemon8 creators by niche, followers and engagement, and keep their latest posts on file.
- **Brand and competitor monitoring**: follow brand accounts and hashtags, and see new, changed and deleted posts on a schedule.
- **Trend research**: read what Lemon8 recommends in Fashion, Food, Beauty, Travel and the other category feeds, market by market.
- **Content planning**: compare saves and views across posts to see which formats and topics people keep.
- **Data and AI teams**: flat rows with text, hashtags and image copies, ready for analysis or a model.

### What data you get

| Row type | Main fields |
| --- | --- |
| `profile` | `username`, `nickname`, `followerCount`, `followingCount`, `likesReceived`, `savesReceived`, `postCount`, `verified`, `bio`, `links`, `avatarUrl` |
| `post` | `id`, `url`, `postType` (gallery, video, article), `title`, `text`, `hashtags`, `likeCount`, `saveCount`, `commentCount`, `viewCount`, `publishedAt`, `imageUrls`, `coverUrl`, `videoUrl`, `videoDurationSeconds`, `authorUsername`, `authorFollowers`, `source` |
| monitoring columns | `changeType` (NEW, UPDATED, EXPIRED), `changedFields`, `previousValues`, `comparedFields` |
| saved media columns | `savedImageUrls`, `savedVideoUrl`, `savedMediaCount`, `mediaNote` |
| `comment` | `id`, `postId`, `text`, `likeCount`, `replyCount`, `createdAt`, `authorNickname`, `isByPostAuthor` |
| `note` | free row: `status` and `note` say why an input returned nothing |

Every post row says where it came from in `source` (`profile:@name`, `keyword:skincare`, `hashtag:#mealprep`, `feed:fashion` or `url`) and its place in that list in `position`.

### How to use

1. Fill one or more of `profileUrls`, `postUrls`, `keywords`, `hashtags` and `feedCategories`.
2. Pick the `region` (market) and how many posts per source with `maxItems`.
3. Keep `includePostDetails` on for full engagement; turn on `includeComments` for comment rows.
4. Click **Start** and download the dataset as JSON, CSV or Excel, or read it through the API.

A creator's profile and latest posts:

```json
{ "profileUrls": ["https://www.lemon8-app.com/@lemon8_us"], "maxItems": 10 }
```

Keywords and hashtags in one run, with comments:

```json
{ "keywords": ["skincare routine", "easy recipes"], "hashtags": ["#mealprep"], "maxItems": 30, "includeComments": true, "maxCommentsPerPost": 10 }
```

The Japanese fashion feed:

```json
{ "feedCategories": ["fashion"], "region": "jp", "maxItems": 50 }
```

A daily run with only what changed (save it as a Task and attach a Schedule):

```json
{ "profileUrls": ["@lemon8_us"], "hashtags": ["skincare"], "maxItems": 30, "monitoringMode": true, "changeFields": ["likes", "saves", "comments", "text"] }
```

A creator's posts with copies of every image and video:

```json
{ "profileUrls": ["@lemon8_us"], "maxItems": 20, "saveImages": true, "saveVideos": true }
```

### Input

| Field | What it does |
| --- | --- |
| `profileUrls` | Profile links (`https://www.lemon8-app.com/@name`) or `@name`. One profile row plus the creator's posts. |
| `postUrls` | Post links (`https://www.lemon8-app.com/@name/<post id>`). One full post row each. |
| `keywords` | Search terms. The keyword's posts, then the hashtag of the same name. |
| `hashtags` | `#name`, `name`, or a hashtag link (`https://www.lemon8-app.com/topic/<number>`). |
| `feedCategories` | foryou, food, beauty, fashion, home, wellness, travel, fitness, parenting, relationship, tech, photography, money, pets, entertainment, career, art, reading, gaming, cars, outdoors, education. |
| `region` | us, uk, ca, au, nz, jp, th, id, vn, my, sg, ph. Default us. |
| `maxItems` | Posts per profile, keyword, hashtag and category, counted separately. 0 returns only profile rows. |
| `includePostDetails` | On (default): views, saves, comment count, date, full text, all images and video link on every post. |
| `includeComments` | Adds comment rows for every returned post. |
| `maxCommentsPerPost` | Comments per post when `includeComments` is on (1 to 500, default 20). |
| `expandKeywords` | On (default): after the keyword page, a keyword continues with the hashtag of the same name and the searches Lemon8 suggests for it. |
| `oldestPostDate` / `newestPostDate` | Date range, like `2026-01-31` or `30 days`. |
| `monitoringMode` | Returns only what changed, per source: NEW, UPDATED and EXPIRED posts. The first run remembers and is free. |
| `changeFields` | What counts as an update in monitoring mode: likes, saves, comments, views, text. Default: likes, saves, comments, text. Empty: only NEW and EXPIRED. |
| `returnExpired` | On (default): a profile post that was deleted since the last run comes back once as EXPIRED. |
| `monitorName` | Optional name for a monitor. Each saved Task already keeps its own memory; use a name to keep monitors apart when you run without a Task. |
| `resetMonitoringState` | Forgets what this monitor remembered (this Task or this `monitorName`). Use once. |
| `resumeFromDataset` | The dataset of an earlier run (pick it, or paste its dataset ID). Posts, comments and profiles already in it are skipped and not charged. |
| `saveImages` / `saveVideos` | Copy each post's images / video into the media store and add the links to the row. Off by default. |
| `maxImagesPerPost` | Images saved per post (1 to 50, default 20). |
| `maxMediaMbytes` | Stop saving files after this many MB in a run (default 500). Rows keep coming. |
| `mediaStoreName` | The named key-value store in your account that keeps the saved files (default `lemon8-media`). |
| `useProxy` | On (default): retries through Apify Proxy if Lemon8 does not answer. |

### FAQ

#### How do I scrape Lemon8 posts by hashtag or keyword?

Put the terms in `hashtags` or `keywords`, pick the `region` and `maxItems`, and click **Start**. Each post comes back as a row with views, saves, likes, comment count, full text, hashtags, images and publish date, and `source` says which term found it.

#### How do I find Lemon8 influencers in a niche?

Search the niche's keywords or hashtags. With `includePostDetails` on (the default), every post row carries `authorUsername` and `authorFollowers`; paste the creators you like into `profileUrls` to get their full profile and latest posts.

#### How do I download Lemon8 images and videos before the links expire?

Turn on `saveImages` and `saveVideos`. Each image and video is copied to a named key-value store in your Apify account and the row gets permanent links in `savedImageUrls` and `savedVideoUrl`, which keep working after Lemon8's own links expire.

#### How can I track likes and saves on Lemon8 posts over time?

Save the input as a Task with `monitoringMode` on and attach a Schedule. Each run returns only `NEW` posts, `UPDATED` posts with the previous values next to the new ones, and `EXPIRED` posts.

#### How do I export a Lemon8 creator's posts to Excel?

Paste the profile link or `@name` into `profileUrls`, set `maxItems`, run it, and download the dataset as Excel or CSV. You get one profile row and one row per post.

#### Do I need a Lemon8 account?

No. No login and no cookies are needed.

### Pricing

You pay per row returned: one price per profile row, per post row and per comment row. Free `note` rows are never charged. With `saveImages` / `saveVideos` on, each image or video copied to storage is charged once, after its post row is delivered; files that could not be saved are not charged. In monitoring mode, unchanged posts are free, and a source with no new, updated or expired post costs one check. Set a maximum total charge on the run and the Actor stops cleanly at that limit, with a free row saying what was not read.

### Good to know

- A removed post, a missing profile, an unknown category or a keyword with no results comes back as one free `note` row that says why, so the rest of the run keeps going.
- A post found by two inputs of the same run (a keyword and a hashtag, say) is returned and charged once, under the first input that found it.
- If `resumeFromDataset` cannot be read, the run stops at once with a free row and charges nothing.
- Lemon8's keyword pages list about 5 to 10 posts per keyword; the rest of a keyword's rows come from the hashtag of the same name and Lemon8's suggested searches, marked in `source`. A very narrow keyword can end before `maxItems`; a free row then says how many were returned.
- A hashtag returns the top posts Lemon8 shows first, then its recent posts page by page. Some large hashtags show visitors only the top posts.
- A profile returns every post its Lemon8 web page lists. `postCount` is Lemon8's own total and can be higher than what the web page lists (on 2026-10-15 one official account listed 218 of 276).
- Lemon8 shows comment replies only inside its app, so replies are counted in `replyCount` but are not returned as rows.
- Without `includePostDetails`, post rows carry only what Lemon8's lists show: title, a text preview, likes and the cover image. The other counts are null, never guessed.
- A hashtag name is matched to the hashtag that real posts use. If Lemon8 has no hashtag with that exact name, the row says so; paste the hashtag link to read it directly.
- A category feed is the stream Lemon8 recommends to a visitor. After a few dozen posts it starts repeating posts already returned, and the run moves on with a free row saying so.
- `createdAtFromId` is the time encoded in the post id (minutes before publishing); `publishedAt` comes from the post page and is set when details are loaded. With details on, date filters use `publishedAt`; with details off, they use `createdAtFromId`.
- Monitoring compares the first `maxItems` posts of each source with the last run. `UPDATED` compares only values that were read both times: without `includePostDetails`, that is likes and the text preview. Views are not compared unless you add them to `changeFields`, because they change on almost every run. `UPDATED` rows do not repeat the post's comments. Each saved Task keeps its own monitoring memory; runs without a Task and without a `monitorName` share one memory per source and region.
- `EXPIRED` is reported for profiles only, and only after the post's own page is gone too. A post that just moved out of the first `maxItems` posts is not expired. An `EXPIRED` row carries the values remembered from the last run.
- Saved files stay in the named store (`lemon8-media` unless you set `mediaStoreName`) until you delete it; Apify bills that storage on your plan like any other stored data. Videos larger than 30 MB are not saved; `mediaNote` says so and the row is still returned.
- Profile and post rows contain only what Lemon8 shows publicly. Emails and phone numbers in bios, post text and comments are replaced with `[email removed]` / `[phone removed]`.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `profileUrls` (type: `array`):

Lemon8 creators to read: profile links like https://www.lemon8-app.com/@lemon8_us, or just @username. Each gives one profile row (followers, likes and saves received, post count, bio, links) plus that creator's posts, newest first. Leave empty if you use other sources.

## `postUrls` (type: `array`):

Single Lemon8 posts to read in full: links like https://www.lemon8-app.com/@username/7499465815561994794. Each gives one post row with all counts, full text, hashtags, images and video link. Leave empty if you use other sources.

## `keywords` (type: `array`):

Search terms as you would type them in the app, for example skincare routine or easy recipes. Each returns the posts Lemon8 lists for that keyword, then continues with the hashtag of the same name until Max posts per source. Leave empty to skip keyword search.

## `hashtags` (type: `array`):

Hashtags with or without #, for example #mealprep, or a hashtag link like https://www.lemon8-app.com/topic/7171967866135248902. Each returns posts from that hashtag. Leave empty to skip hashtags.

## `feedCategories` (type: `array`):

Lemon8 category feeds, one per line: foryou, food, beauty, fashion, home, wellness, travel, fitness, parenting, relationship, tech, photography, money, pets, entertainment, career, art, reading, gaming, cars, outdoors, education. Leave empty to skip feeds.

## `region` (type: `string`):

Lemon8 market to read. Keywords, hashtags and feeds return different posts in each market. United States if not set.

## `maxItems` (type: `integer`):

How many posts to return for each profile, keyword, hashtag and category, counted separately. Post URLs always return their post. 0 returns only the profile rows of Profile URLs.

## `includePostDetails` (type: `boolean`):

On: opens each listed post to add full text, publish date, views, saves, comment count, every image, hashtags, the video link and the creator's followers. Off: returns only what the list shows (title, text preview, likes, cover image), which is faster.

## `includeComments` (type: `boolean`):

Adds the comments of every returned post as their own rows (text, likes, reply count, date, commenter display name, whether the creator wrote it). Off by default.

## `maxCommentsPerPost` (type: `integer`):

How many comments to return for each post when Include comments is on, in the order Lemon8 shows them. From 1 to 500.

## `expandKeywords` (type: `boolean`):

Lemon8's keyword pages list about 5 to 10 posts. On: a keyword then continues with the hashtag of the same name and with the searches Lemon8 suggests for it, until Max posts per source; those rows say so in the source column. Off: only the keyword page.

## `oldestPostDate` (type: `string`):

Return only posts published on or after this date. Use 2026-01-31, or a relative value like 30 days. Empty means no lower limit.

## `newestPostDate` (type: `string`):

Return only posts published on or before this date (2026-01-31 includes that whole day, UTC). Empty means no upper limit.

## `monitoringMode` (type: `boolean`):

Run on a schedule and get only what changed for each profile, keyword, hashtag and category: new posts (NEW), posts whose likes, saves, comments or text changed (UPDATED), and deleted profile posts (EXPIRED). Unchanged posts are not returned or charged. The first run only remembers what is there now and is free; later runs with no change cost one check per source. Profile rows are not repeated in this mode.

## `changeFields` (type: `array`):

In monitoring mode, posts returned before come back marked UPDATED when one of these values changed since the last run. Views change on almost every run, so they are not selected by default. Leave empty to get only NEW and EXPIRED posts.

## `returnExpired` (type: `boolean`):

In monitoring mode, a profile post that was there last run and is now gone from the profile and its own page is returned once, marked EXPIRED, with the values remembered from before. Off means deleted posts are not reported.

## `monitorName` (type: `string`):

Optional. A name for this monitor, like brand-a-weekly. Each saved Task already keeps its own memory; give a name when you start monitoring runs without a Task (API, schedules on the Actor), so two monitors of the same profile or hashtag do not share what they remember. Empty: the Task keeps its own memory, and runs without a Task share one.

## `resetMonitoringState` (type: `boolean`):

Forget what this monitor remembered (this Task, or this monitor name), so its next run starts over. Other monitors keep their memory. Use once, then turn off.

## `useProxy` (type: `boolean`):

If Lemon8 does not answer, retry through Apify's datacenter proxy, and look up hashtag names through a residential connection. Off means direct connection only.

## `resumeFromDataset` (type: `string`):

Optional. Pick the dataset of an earlier run of this Actor, or paste its dataset ID (the part after /datasets/ in the dataset link). Posts, comments and profiles already in it are skipped: not returned and not charged, and the run keeps going to the next ones. If the dataset cannot be read, the run stops at once with a free row and charges nothing. Empty means start fresh.

## `saveImages` (type: `boolean`):

Download each returned post's images into the media store below and add their links in savedImageUrls (same order as imageUrls). A file that cannot be saved is null and mediaNote says why; the post row is still returned. Off by default.

## `saveVideos` (type: `boolean`):

Download the video of each returned video post into the media store below and add its link in savedVideoUrl. Needs post details on. Videos over 30 MB are not saved. Off by default.

## `maxImagesPerPost` (type: `integer`):

How many images of each post to save, in the order Lemon8 shows them. From 1 to 50.

## `maxMediaMbytes` (type: `integer`):

Stop saving images and videos once this many megabytes were saved in this run. Rows keep coming; later files are null with a note. From 1 to 10000.

## `mediaStoreName` (type: `string`):

Name of the key-value store in your Apify account that keeps the saved images and videos. It is created on first use and kept until you delete it, so the links in the rows keep working. 3 to 63 letters, digits and hyphens. Empty means lemon8-media.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.lemon8-app.com/@lemon8_us"
  ],
  "region": "us",
  "maxItems": 10,
  "includePostDetails": true,
  "includeComments": false,
  "maxCommentsPerPost": 20,
  "expandKeywords": true,
  "monitoringMode": false,
  "changeFields": [
    "likes",
    "saves",
    "comments",
    "text"
  ],
  "returnExpired": true,
  "resetMonitoringState": false,
  "useProxy": true,
  "saveImages": false,
  "saveVideos": false,
  "maxImagesPerPost": 20,
  "maxMediaMbytes": 500,
  "mediaStoreName": "lemon8-media"
}
```

# Actor output Schema

## `results` (type: `string`):

Rows of three types, marked in the type column: profile (followers, following, likes and saves received, post count, bio, links), post (title, full text, hashtags, likes, saves, comments, views, publish date, image and video URLs, creator, and the source it came from) and comment (text, likes, reply count, date, commenter display name). In monitoring mode only new posts are returned. Invalid input, missing posts and empty sources come back as free rows of type note that say why.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "profileUrls": [
        "https://www.lemon8-app.com/@lemon8_us"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/lemon8-scraper-all-in-one").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "profileUrls": ["https://www.lemon8-app.com/@lemon8_us"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/lemon8-scraper-all-in-one").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "profileUrls": [
    "https://www.lemon8-app.com/@lemon8_us"
  ],
  "maxItems": 10
}' |
apify call neverempty/lemon8-scraper-all-in-one --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/lemon8-scraper-all-in-one"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/H0MwnefGXcVfZ1Qkm/builds/yNkdYSavwUbvKjEWD/openapi.json
