WEBTOON Scraper - Series, Episodes, Genres & Rankings
Pricing
from $1.00 / 1,000 series or episode records
WEBTOON Scraper - Series, Episodes, Genres & Rankings
Scrape the WEBTOON catalog into structured data. Extract series, genres, rankings and complete episode lists, including titles, authors, descriptions, thumbnails and other available series and episode details.
Pricing
from $1.00 / 1,000 series or episode records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
WEBTOON Scraper: Series Catalog, Episode Lists and Details
WEBTOON Scraper turns the public WEBTOON catalog into structured data, no account needed. Search by keyword, browse a genre, weekday schedule, ranking chart or canvas tab, or paste WEBTOON links directly, then optionally expand every discovered series into its episode list. Get series metadata (authors, summary, schedule, view and subscribe counts) and episode rows (episode number, publish date, likes, thumbnails) across seven language editions, then export to JSON, CSV or Excel, or pull results straight into your app through the API. Episode reader (viewer) pages are always out of scope: this actor reads catalog and series-list pages only.
Why This Scraper?
- Five ways to find data. Search by keyword, browse a genre, a weekday schedule, a ranking chart or a canvas tab, or paste WEBTOON links directly. No need to build URLs by hand.
- Detail enrichment on demand. Turn on series detail reads to pull authors, summary, schedule text and view/subscribe counters that no catalog card carries.
- Episode expansion is opt-in. Switch it on to walk every discovered series' episode list and emit one row per episode, or leave it off for lean, series-only runs.
- One shared cap. A single
maxItemslimit spans every series and episode row together, so cost stays predictable, and the series row is always emitted before its episodes for readable grouping. - Resume and incremental modes. Continue an interrupted crawl, or track a scope across scheduled runs and return only new, updated and reappeared series.
- Loud failures, not silent empties. A refused run fails with a clear message instead of returning a dataset that looks like an empty search.
- Reader pages stay out of scope. Pasted episode viewer links are rejected with a clear message instead of being silently dropped or attempted.
Use Cases
- Webtoon and manhwa aggregators: mirror new releases, genre rankings and episode drops across languages into your own catalog or app.
- Content and licensing scouts: track rising titles by rank, likes and subscriber counts before they trend, using the ranking and genre modes.
- Reading-list and notification tools: monitor a shortlist of series URLs on a schedule and alert on new episodes with incremental mode.
- Localization and translation teams: compare titles, genres and publication schedules across the seven catalog language editions.
- Market and fandom research: build historical datasets of view counts, subscribe counts and genre popularity for analysis.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
kind | "webtoon" (also "episode") |
recordId | "en-title-500001" (episode rows: "en-ep-500001-42") |
titleNo | 500001 |
title | "Sample Series Title" |
url | Public WEBTOON page URL |
language | "en" |
genre | "Fantasy" (series rows only) |
webtoonType | "originals" (also "canvas") |
sourcePage | "genre" (also "daily", "ranking", "search", "canvas", "series") |
author / authors | "Sample Author" / ["Sample Writer", "Sample Artist"] |
summary | "A short sample summary of the series premise." |
scheduleText / pageSchedule | "Every Monday" / "Monday" (pageSchedule is set on weekday-schedule and series pages) |
rank | 12 (ranking pages only) |
badge | "NEW" (also "UP") |
likeCount / likeCountRaw | 245000 / "245K" |
viewCount / subscribeCount | 12000000 / 340000 (read from the series page: with Fetch series details, or for a pasted series URL) |
latestEpisode | { "episodeNo": 42, "title": "Episode 42", "date": "Sep 20, 2026" } (series rows only) |
seriesRecordId / seriesTitleNo / seriesTitle | episode rows only, link back to the parent series |
episodeNo | 42 (episode rows only) |
date | "Sep 20, 2026" (episode publish date) |
likeCountText / isRecentlyUpdated | "12.3K" / true (episode rows only) |
imageUrl | Series or episode thumbnail URL |
referer | "https://www.webtoons.com/", required as the HTTP Referer header when displaying imageUrl |
changeType / changedFields | Incremental state classification and changed field names (incremental mode only) |
firstSeenAt / lastSeenAt | ISO timestamps for the record's tracked lifetime (incremental mode only) |
How to Use
- Pick a mode:
search(keyword, genre, schedule or canvas) orurl(paste WEBTOON links). - For search mode, set a keyword or a genre/weekday/canvas selection; for URL mode, paste one or more catalog or series links.
- Turn on Fetch series details and/or Include episodes if you need more than the catalog row, and set Max items to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Browse a genre:
{"mode": "search","genre": "drama","language": "en","maxItems": 20}
Search by keyword (genre rows follow the keyword hits, see below):
{"mode": "search","keyword": "moonlit sample saga","searchType": "all","maxItems": 15}
Search and expand every discovered series into episode rows. The six-row cap includes the series row and all episode rows together:
{"mode": "search","genre": "drama","includeEpisodes": true,"maxItems": 6,"maxPages": 1}
Process a known series URL:
{"mode": "url","urls": ["https://www.webtoons.com/en/fantasy/sample-series/list?title_no=00000000"],"includeEpisodes": true,"maxItems": 12}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/webtoons-com-scraper").call(run_input={"mode": "search", "genre": "drama", "maxItems": 20})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["kind"], row["title"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/webtoons-com-scraper').call({ mode: 'search', genre: 'drama', maxItems: 20 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
How the shared cap and episode expansion interact
Series rows and episode rows draw from the same maxItems budget, and the series row for each discovered title is always emitted before its episodes. A run with maxItems: 20 can therefore return one series plus nineteen episodes, or up to twenty series-only rows when includeEpisodes is off. maxPages bounds how many episode-list pages are walked per series, but it never raises maxItems. When a series' episode expansion is refused, the actor keeps the catalog row it already had instead of dropping the series entirely.
What a search-mode run browses
Search mode reads its scopes in this order: the keyword search (when a keyword is set), the weekday schedule (when a weekday is set), then the genre page. With the originals source the genre always has a value (empty falls back to drama), so a keyword or weekday run also returns rows from that genre page after the earlier scopes, until maxItems is reached. Every row's sourcePage names the scope it came from: keep sourcePage "search" for keyword hits only. With the canvas source and no keyword, only the canvas tab is read.
Set Max pages per series when you include episodes
Episode lists are read 10 episodes per page. Set maxPages to the number of pages you need (for example 5 for the newest 50 episodes). With maxPages at 0, the end of a longer episode list is not always detected, so the run can keep re-reading the last page until maxItems or the run timeout stops it; a series with exactly two pages of episodes can also return only its first page.
Detail reads back off automatically
When Fetch series details is on and Include episodes is off, the run turns detail reads off for the rest of that run after 5 failed or refused detail reads in a row, or once more than 60% of detail reads have failed after at least 6 attempts, and ships list-page rows instead. This keeps one blocked batch of detail pages from slowing down the whole run. A failed detail read is never charged; the surcharge applies only to rows whose detail read succeeded.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: point it at a prior run or dataset ID and the actor skips every record already collected there, so you don't pay twice. With Include episodes on in search mode (or for pasted genre, schedule, ranking, search or canvas pages), a series whose row was already collected is skipped as a whole, so episodes the interrupted run had not reached are not picked up; paste that series' own URL in URL mode to finish it. It cannot be combined with Incremental mode on a run that already has a stored incremental baseline; use one mechanism at a time for a given scope. - Incremental mode (
incrementalMode) is for scheduled runs over the same scope. Each record is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED, orEXPIRED(only withemitExpiredon, and only after a run with nomaxItemscap hit, no resume, and no refused or errored scope). Episode rows are the exception: episodes beyondmaxPages, or on an episode page that was refused while expanding a search or catalog-page result, count as gone, so keepemitExpiredoff when you track episodes withincludeEpisodes.stateKeynames or shares the stored state. With incremental mode off, output is exactly as before.
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.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | Search the catalog or process pasted URLs |
keyword | string | empty | Title keyword to search; with the originals source the genre page is also read after the keyword hits |
searchType | string | all | Keyword index: all, originals, or canvas |
language | string | en | Catalog language edition |
source | string | originals | Catalog to browse when no keyword is set: originals or canvas |
genre | string | drama | Genre (or canvas tab) to browse; falls back to drama (or ALL for a canvas source) when left empty or unknown |
sortOrder | string | MANA | Genre ordering: MANA (popularity), LIKEIT (likes), or UPDATE (recency) |
weekday | string | empty | Weekday schedule to browse (monday to sunday); the genre page is read after it |
urls | array | sample genre URL | Catalog or series URLs in URL mode |
fetchDetails | boolean | false | Read each series page for authors, summary and counters; adds a per-series surcharge |
includeEpisodes | boolean | false | Emit one row per episode for every discovered series; shares the maxItems cap with series rows |
maxItems | integer | 20 | Total cap across series and episode rows (the only default cap) |
maxPages | integer | 0 | Episode-list pages per series (10 episodes each); 0 means uncapped (maxItems still applies). Set it when you include episodes |
resumeFromRunId | string | empty | Continue an interrupted crawl from a previous run or dataset ID |
incrementalMode | boolean | false | Track this scope across runs and stamp NEW, UPDATED, UNCHANGED, REAPPEARED, EXPIRED |
stateKey | string | empty | Custom incremental state key; leave empty to derive one from the full scope |
emitUnchanged | boolean | false | Also return (and bill) UNCHANGED rows |
emitExpired | boolean | false | Also return (and bill) EXPIRED rows, only after a complete, uncapped scan |
mcpConnectors | array | empty | Optional: send a summary of each record to apps you authorized under Integrations |
notionParentPageUrl | string | empty | Notion connector only: page under which records are created |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run |
proxy | object | Apify RESIDENTIAL | Apify Proxy connection; defaults to the RESIDENTIAL group and accepts overrides |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"kind": "webtoon","recordId": "en-title-500001","titleNo": 500001,"title": "Sample Series Title","url": "https://www.webtoons.com/en/fantasy/sample-series-title/list?title_no=500001","language": "en","genre": "Fantasy","webtoonType": "originals","sourcePage": "ranking","rank": 12,"badge": "NEW","likeCountRaw": "245K","likeCount": 245000,"author": "Sample Author","authors": ["Sample Writer", "Sample Artist"],"summary": "A short sample summary of the series premise.","scheduleText": "Every Monday","pageSchedule": null,"viewCount": 12000000,"subscribeCount": 340000,"latestEpisode": {"episodeNo": 42,"title": "Episode 42","date": "Sep 20, 2026"},"imageUrl": "https://webtoon-phinf.pstatic.net/sample_thumb.jpg","referer": "https://www.webtoons.com/"}
Image display requirement: send the record's referer value as the HTTP Referer request header when downloading or displaying imageUrl.
Episode rows carry a different shape: kind: "episode", plus seriesRecordId, seriesTitleNo, seriesTitle, episodeNo, date, likeCountText, likeCount, isRecentlyUpdated, imageUrl, referer and language. In incremental mode, any record can also carry changeType, changedFields, firstSeenAt and lastSeenAt.
Plan Requirement
The default proxy setting works out of the box on the RESIDENTIAL group. A paid Apify plan may be useful for larger runs, since series detail reads and every emitted row are billed separately. Keep fetchDetails and includeEpisodes off for the lowest-cost, series-only behavior.
FAQ
How much does it cost?
You pay per record returned, plus an optional per-series detail-read surcharge when Fetch series details is on. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.
Is it legal to scrape WEBTOON?
This actor collects only publicly available catalog data: no account, and no reader (viewer) pages, which are account-scope and are never fetched. You are responsible for how you use the data: follow WEBTOON's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Titles, artwork and summaries may be subject to third-party rights.
Can I get only new or changed series on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared records; unchanged ones are suppressed and not billed unless Emit UNCHANGED rows is on.
Why did Include episodes return fewer rows than I expected?
Series rows and episode rows share one Max items cap, and the series row is emitted first, so a low cap can be used up before every episode is read. Raise Max items, or use Max pages per series to bound how many episode-list pages each series walks instead.
Why did my run fail instead of returning an empty dataset?
If every scope is refused, the run stops with a clear message so "no matches" is never confused with "nothing could be read". Run it again in a few minutes. If only some scopes could be read, you still get what was found and the run succeeds; the run log names each scope that was refused or errored.
Why does my keyword search also return genre rows?
With the originals source, search mode reads the genre page (default drama) after the keyword results, and fills the rest of Max items from it. Filter the dataset on sourcePage "search" to keep only keyword hits, or lower Max items.
Can I use resume and incremental mode together?
Not on the same scope. resumeFromRunId continues one interrupted run without re-billing already-collected records. incrementalMode tracks a scope across scheduled runs instead. Combining both on a run that already has a stored incremental baseline is rejected; use one mechanism at a time.
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.
🔗 More scrapers you might like
Pair this actor with these related scrapers from the same team:
| ⚽ JioHotstar Scraper Scrape the JioHotstar catalog by content type or URL. Extract shows, movies, episodes... | 🧩 TuneIn Scraper Scrape TuneIn by keyword, category, genre, location or URL. Extract stations and podcasts... |
| 🧩 AniList Anime & Manga Scraper Scrape AniList anime and manga: titles (romaji/English/native), scores, popularity... | 🧩 Pocket Casts Podcast Scraper Scrape Pocket Casts podcast data, including listener ratings, full episode archives... |
| 📱 ViewStats Scraper Scrape YouTube channel analytics from ViewStats. Look up channels by handle, URL, or... | 🧩 MyAnimeList Scraper Scrape MyAnimeList anime and manga by keyword, ranking chart or URL. Extract titles... |
💬 Support & custom scrapers
- 🐞 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 abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.