Lemon8 Media Scraper: Images, Videos & Downloads avatar

Lemon8 Media Scraper: Images, Videos & Downloads

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Lemon8 Media Scraper: Images, Videos & Downloads

Lemon8 Media Scraper: Images, Videos & Downloads

Lightweight Lemon8 scraper for extracting image and video URLs from posts, with optional media downloads. Built for fast, clean media collection without comments, captions, or other post details.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

9

Total users

2

Monthly active users

8 days ago

Last modified

Features

Limited permissions

Share

Lemon8 Media Scraper: Image and Video URLs from Any Post

Lemon8 Media Scraper turns any Lemon8 post, or a batch of posts found by keyword, into a clean feed of image and video URLs. Paste post links or set a search term and region, and get every media URL a post carries, already upgraded to its higher-quality variant, with an option to download the actual files into the run's storage. Schedule it and turn on incremental mode to get only new and changed posts on every run, then export the results as JSON, CSV or Excel, or read them through the API.

Why This Scraper?

  • Two ways to find posts. Paste exact Lemon8 post links, or search by keyword and region through Lemon8's discovery page.
  • Clean media, nothing else. Every image and video URL from a post, with thumbnails converted to their higher-quality variant by default.
  • Optional file download. Pull the actual image and video files into the run's storage, not just links, when you need copies rather than references.
  • Any Lemon8 region. Point it at the region code for the market you care about, the same way the Lemon8 app itself is localized.
  • Built for schedules. Turn on incremental mode and recurring runs return only new and changed posts, not the same posts every time.
  • Resume without re-paying. Continue an interrupted pull by pasting its run or dataset id, and posts already collected there are skipped.
  • Pipe results into your apps. Send a summary of every record to Notion, Linear or Airtable through Apify's connectors, no extra script needed.

Use Cases

  • Content archiving: save images and videos from posts before they are edited or taken down.
  • Dataset building: collect batches of images and videos for a training or research dataset.
  • Visual trend research: track the styles, colors and formats trending in a niche or region.
  • Competitor and creator monitoring: watch an account's or a keyword's posts on a schedule and catch new content as soon as it is up.
  • Personal backup: pull your own account's post media out of Lemon8 into your own storage.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
postId, groupId"7543408422994264589"
postUrl, url"https://www.lemon8-app.com/@username/7543408422994264589?region=us"
title, contentpost title and text without HTML
articleClasspost type, for example Gallery or Video
likes, saves, commentCountengagement counts
authorUserId, authorUsername, authorNicknamethe author
authorAvatar, authorFollowersauthor avatar and follower count
hashtagshashtags on the post
topCommentsup to 5 comments from the post page (text, likes, replies, author, time)
imageCount, videoCount2, 0
imagesarray of image objects, one per extracted image
images[].url"https://example-cdn.lemon8-app.com/sample-image-1.webp"
images[].alt, images[].type"", "image"
images[].keystoreKey"7543408422994264589_img_0.webp" (only when downloadMedia is on)
videosarray of video objects, one per extracted video
videos[].url, videos[].postervideo file and its poster image
videos[].keystoreKey"7543408422994264589_vid_0.mp4" (only when downloadMedia is on)
videoUrl, thumbnailUrlvideo file (video posts only) and cover image
keyword, category, regionhow the post was reached
sourceMode, scrapedAtmode used and scrape time
changeType"NEW" (incremental mode only)
changedFields["videos"] (incremental mode only)
firstSeenAt, lastSeenAt"2026-07-31T03:00:00Z" (incremental mode only)

The post detail fields come from the same post page as the media, so they add no extra requests. In incremental mode the counts, comments, follower count, scrapedAt and the source fields are returned but never make a post UPDATED.

The last four fields (changeType, changedFields, firstSeenAt, lastSeenAt) are added only when incrementalMode is on. A normal run's rows carry the media fields and the post detail fields above, nothing more.

Output views

The dataset has these views in the Console: Media Overview (title, author, engagement and counts), Images, Videos, Post Details (text, hashtags, comments, source fields) and Changes (incremental fields). Every field is declared in the dataset schema, so exports have stable columns.

How to Use

  1. Choose your input: paste specific post URLs, or set a search term and region to find posts by keyword.
  2. Pick which media to keep (images, videos, or both), and whether to only collect links or also download the files.
  3. Set Limit to control how many posts are processed and how much the run costs, then click Start.
  4. Read the results from the dataset, or download them as JSON, CSV or Excel.

Search discovery in one region:

{
"searchTerm": "skincare",
"region": "us",
"limit": 20,
"saveImages": true,
"saveVideos": true
}

Direct post URLs with file download:

{
"postUrls": [
"https://www.lemon8-app.com/@username/7543408422994264589",
"https://www.lemon8-app.com/@another/7550145067198005791"
],
"downloadMedia": true
}

Recurring monitoring with incremental mode:

{
"searchTerm": "streetwear",
"region": "sg",
"limit": 50,
"incrementalMode": true,
"stateKey": "streetwear-sg-watch"
}

Resume an interrupted pull:

{
"searchTerm": "travel",
"region": "au",
"limit": 100,
"resumeFromRunId": "<previous run or dataset id>"
}

Modes

ModeInput usedWhat you get
auto (default)postUrls, else searchTermYour own URLs if you set any. The example postUrls run only when you set none of the search or saved-task inputs listed under "Default changed" below; otherwise a keyword search.
postpostUrlsThe posts you list.
discoverkeywords, regionAbout 50 posts per keyword, in order, up to the cap.
profileprofileUrlsPosts linked from each profile page or @username.
feedfeedCategoriesFirst page of each category feed, about 10 posts each.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/lemon8-media-scraper").call(run_input={"searchTerm": "fashion", "region": "us", "limit": 20})
for post in client.dataset(run["defaultDatasetId"]).iterate_items():
print(post["postId"], post["imageCount"], post["videoCount"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/lemon8-media-scraper').call({ searchTerm: 'fashion', region: 'us', limit: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Resume and recurring updates

  • Resume (resumeFromRunId) points this run at a previous run or dataset id so the actor knows which posts it already saw there.
  • Incremental mode (incrementalMode) is for scheduled runs over the same posts or search. Each row is classified NEW, UPDATED (with changedFields), or UNCHANGED (suppressed and not billed unless emitUnchanged is on). EXPIRED is never detected unless emitExpired is on, and even then only once a run has scanned every tracked post to its natural end; a capped run or a resumed run skips EXPIRED detection that time rather than risk a wrong result. REAPPEARED shows up only when a post previously marked EXPIRED by such a run is found again on a later run, it does not appear on a first run or under normal NEW/UPDATED conditions. Ignore fields when detecting changes (ignoreFieldsForChanges): list field names, or a dotted path such as images.alt for a key inside every item of a list, that must not make a post UPDATED or appear in changedFields. The fields stay in the output; changing the list never re-marks your saved baseline as updated. Rotating CDN signatures and hostnames in image and video links are already ignored automatically.
  • stateKey names or shares the stored state. Leaving it empty derives a key from the mode and its inputs (postUrls/searchTerm, keywords, profileUrls or feedCategories), region and the media options, so two differently configured runs never mix state. Raising limit alone never starts a new baseline.
  • Cosmetic link changes (a different delivery host, or a refreshed access token on an otherwise identical image or video) are normalized before comparing posts, so a post whose media has not actually changed is never marked UPDATED just because its link was reissued.
  • With incremental mode off, output is exactly as in a normal run.

URL Mode

postUrls accepts these URL shapes (tracking parameters such as utm_source are ignored):

ShapeExampleBehaviour
Post detailhttps://www.lemon8-app.com/@05luvlee/7535454724489986574?region=usScrapes that post. ?region= is optional.
Discovery (/discover/<term>, older path)https://www.lemon8-app.com/discover/fashion?region=usLists posts for that keyword, up to Limit.
Discovery (/experience/<term>)https://www.lemon8-app.com/experience/fashion?region=usSame as above.
Discovery in another regionhttps://www.lemon8-app.com/discover/fashion?region=jpThe region is taken from the URL.
Feed (/feed/<category>)https://www.lemon8-app.com/feed/foodScrapes the first page of that category feed (about 10 posts).
Profile pagehttps://www.lemon8-app.com/@05luvlee?region=usScrapes the posts linked from the profile page, up to Limit.
Topic page (/topic/<id>)https://www.lemon8-app.com/topic/6880245568946880518?region=usScrapes the posts linked from the topic page, up to Limit. sourceMode is topic.

The postUrl field of a post URL you pass is returned exactly as you typed it (a relative path gets the site host added). If none of your URLs is supported, the run ends with the status message No supported Lemon8 URL in postUrls.

Anything else (/tag/, /hashtag/, /search?q=, a bare numeric id, or the v. and m. hosts) is skipped and logged as a warning that starts with WARNING: unsupported URL skipped.

Default changed: postUrls now ships with one example URL per shape above. In auto mode the examples run only when you leave the list untouched and set none of the following: a searchTerm other than "fashion", keywords, profileUrls, incrementalMode, stateKey, resumeFromRunId, or a region other than us. If you set any of those and leave the example list as is, the examples are dropped: keywords or a custom search term run a keyword search, profileUrls scrape those profiles, and the other settings run the keyword search for searchTerm in your region, so saved tasks and schedules that never sent postUrls keep their earlier behavior and their saved incremental state. To search by keyword with no other setting, clear the list. postUrls always runs when it holds your own URLs.

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.

Input Parameters

ParameterTypeDefaultDescription
postUrlsarrayfive example URLs (one per supported shape)Lemon8 URLs to scrape, see URL Mode above. When this holds your own URLs, searchTerm is ignored; the example list is dropped in the cases listed under "Default changed".
searchTermstring"fashion"Search keyword used to find posts on Lemon8's discovery page. Used when postUrls is empty, when the example postUrls are dropped (see "Default changed"), and in discover mode when Keywords is empty.
modestring"auto"auto (your own postUrls if set, else searchTerm; see "Default changed"), post, discover (keywords), profile (profile URLs) or feed (category feeds). A chosen mode uses only its own input.
keywordsarraynoneKeywords for discover mode, about 50 posts each, taken in order up to the cap. Also used in auto mode once postUrls is cleared.
profileUrlsarraynoneProfile pages or @usernames for profile mode.
feedCategoriesarray["foryou"]Feed mode: foryou, food, beauty, fashion, home, fitness, health, relationship, travel, photography, pet, reading, cars, outdoors (first page of each, about 10 posts). A /feed/<category> URL in postUrls works too.
regionstring"us"Region code passed to Lemon8 (for example us, au, nz, jp, th, id, vn, my, sg, ca). This is a free-text field, not a fixed list.
limitinteger2Maximum number of posts to return, from 1 to 1000.
saveImagesbooleantrueExtract image URLs from each post.
saveVideosbooleantrueExtract video URLs from each post.
downloadMediabooleanfalseAlso download each image and video file into the run's key-value store, increasing run time and storage.
highQualitybooleantrueConvert thumbnail image URLs to their higher-quality variant.
proxyobjectnone (prefill shown in the console: a managed connection for country US)Connection settings for requests. When the managed connection is turned on, the actor also keeps an alternate connection in reserve and switches to it automatically if a request is refused twice in a row. Leaving it off sends requests directly, with no automatic switch.
resumeFromRunIdstringnonePaste a previous run or dataset id to seed this run with the posts it already found there.
incrementalModebooleanfalseTurn on for daily or recurring monitoring, so a run returns only new and changed posts against the previous run.
stateKeystringnoneName a monitoring campaign explicitly, or leave empty to derive one automatically from the mode and its inputs (postUrls/searchTerm, keywords, profileUrls or feedCategories), region and the media options.
emitUnchangedbooleanfalseAlso return (and bill) posts that have not changed since the last run, marked UNCHANGED.
emitExpiredbooleanfalseAlso return (and bill) posts that were present before but are no longer found, marked EXPIRED, once a run fully scans every tracked post.
ignoreFieldsForChangesarraynoneIncremental mode: field names or dotted paths (for example images.alt) that never make a post UPDATED. The fields stay in the output.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run, from 1 to 1000. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"postId": "7543408422994264589",
"postUrl": "https://www.lemon8-app.com/@username/7543408422994264589?region=us",
"images": [
{
"url": "https://example-cdn.lemon8-app.com/sample-image-1.webp",
"alt": "",
"type": "image"
}
],
"videos": [
{
"url": "https://example-cdn.lemon8-app.com/sample-video-1.mp4",
"poster": "https://example-cdn.lemon8-app.com/sample-poster-1.webp",
"type": "video"
}
],
"imageCount": 1,
"videoCount": 1
}

Plan Requirement

On paid Apify plans the default datacenter connection works and no residential proxy plan is needed: Lemon8 pages loaded in testing through Apify datacenter proxies on a paid account. The only block seen was a rare one-off HTTP 429 on a post link carrying extra tracking parameters, which the actor retries on the same connection. Apify free plans do not include Apify proxy access at all, so on a free plan the actor logs a notice and continues on a backup connection, and fails with a clear message if no page can be loaded.

The default proxy input uses the managed connection for the selected region. If a request is refused twice in a row, the actor switches to an alternate connection and logs: "Served over the backup connection (the default connection was unavailable)." If the connection is refused for the account, the run logs a notice that Apify free plans do not include residential proxies and continues on the backup connection. If no page can be read at all, the run fails with a clear message (for example "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search.") instead of returning an empty success. Leaving the proxy input off sends requests directly.

FAQ

How much does it cost?

Pricing is pay per event: one actor start event per run (apify-actor-start) and one dataset item event per row pushed to the dataset (apify-default-dataset-item). The Pricing tab on the actor page shows the current rates for your plan. Nothing else is charged: no extra fee for comments, downloads or modes, and suppressed UNCHANGED rows in incremental mode are not billed. Use Limit (hard cap 1000 per run) to cap the size, and therefore the cost, of any run.

This actor collects only media URLs from publicly viewable Lemon8 posts. You are responsible for how you use the results: follow Lemon8's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. The images and videos themselves may carry their own copyright or other rights held by the original poster.

Can I get only new or changed posts on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and changed posts, and unchanged ones are not billed unless you turn that on too.

Why did a run return no items instead of some media?

If the given post URLs could not be read (deleted, private, or an unrecognized page), or a search and region combination matched nothing, the run stops with a clear status message and returns nothing rather than a placeholder row. This is a normal, successful outcome, not a failure.

Why might a run fail instead of returning an empty result?

A run fails outright only when resumeFromRunId points to a run or dataset that cannot be read (a bad or inaccessible id), or when incrementalMode is combined with resumeFromRunId while saved incremental state already exists for that state key (remove one or set a different stateKey). Individual posts that fail to load are skipped and logged, they don't fail the whole run.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

πŸ”— Want more Lemon8 data?

Pair this actor with these related scrapers from the same team:

πŸ“± Lemon8 Feed Scraper
Scrape Lemon8 feeds across 22 categories and 10+ regions. Extract posts, images, videos...
πŸ“± Lemon8 Profile Scraper
Scrape Lemon8 user profiles with automated multi-profile discovery. Extract profile data...
πŸ“± Lemon8 Search Scraper
Scrape Lemon8 posts by keyword across multiple regions. Extract posts, images, videos...
πŸ“± Universal Media Extractor
Extract videos, audio, and metadata from 1000+ websites including YouTube, TikTok...
πŸ“± Reddit⚑ Lightning
Scrape Reddit posts, comments, and media from any subreddit or user profile - no login or...
πŸ“± Truth Social Scraper
Scrape public Truth Social profiles, posts, media, metrics, author data, and complete...

πŸ‘‰ Browse all abotapi scrapers

πŸ’¬ Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • πŸ› οΈ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.