MyAnimeList Scraper - Anime, Manga, Rankings & Scores
Pricing
from $1.20 / 1,000 anime or manga records
MyAnimeList Scraper - Anime, Manga, Rankings & Scores
Scrape MyAnimeList anime and manga by keyword, ranking chart or URL. Extract titles, scores, ranks, members, genres, studios, authors, synonyms and full synopses. Supports top, airing, upcoming, popular and favorite rankings, plus resume and incremental monitoring.
Pricing
from $1.20 / 1,000 anime or manga records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
14 days ago
Last modified
Categories
Features
Share
MyAnimeList Scraper: Anime & Manga Scores, Reviews, Characters & Charts
MyAnimeList Scraper turns MyAnimeList into a clean anime and manga data feed. Search by keyword, walk any of the five ranking charts, or paste detail-page links, and get titles, scores, member counts, synopses, genres, studios, reviews, characters, voice actors, staff and related entries for every anime or manga. Resume an interrupted run or schedule incremental runs that report only what changed, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Deep search. Walks MyAnimeList search results forward through every page, not just page 1.
- Five charts. Covers all five ranking charts (top, airing, upcoming, most popular, most favourited) for anime and manga.
- Rich records. Enriches records with related entries, character and staff previews, voice actors, paginated reviews and full stats.
- Paste links. Reads pasted detail-page links, anime and manga mixed, auto-detected.
- Built for schedules. Resume from a previous run and incremental monitoring are built in.
- One row per title. Keeps the main dataset to one row per anime or manga, including nested review and preview lists.
- Safe on stop. Pushes each record the moment it is ready, so a stopped run keeps its data.
Use Cases
- Anime and manga database or wiki sites: build a structured catalogue from search or ranking-chart walks, complete with synopsis, genres, related entries and staff.
- Fan communities, bots and newsletters: watch a favourite chart or a saved list of titles with incremental mode, and post only what is NEW, UPDATED or REAPPEARED since the last run.
- Review and sentiment research: collect review text, ratings and recommendation tags across many titles for analysis.
- Discovery and recommendation tools: follow related-entry links plus character and voice-actor previews to map franchises and adaptations.
- Market and studio tracking: monitor the airing, upcoming and most-popular charts to see which studios and producers are trending.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
One record per anime or manga. With fetchDetails on (the default), the record also contains the entry's three review previews by default, plus the characters and voice actors shown there, staff, and related entries. Set maxReviews above 3 to read paginated review pages, or 0 to follow the available review pages up to a ceiling of 5000 reviews per record (the maximum for maxReviews). reviewsComplete tells you whether the collection reached the end of the visible pages. Some titles report more reviews than their pages expose; reviewCountGap records that difference. The character and staff lists remain previews. Other detail fields include Japanese, French and English titles, manga volumes and chapters, synonyms, episodes, ranked and popularity positions, favorites, licensors, producers, studios, authors, demographics, serialization, premiere, broadcast, source, duration, rating and review sentiment counts (reviewBreakdown).
| Field | Example |
|---|---|
id | MyAnimeList's numeric id. (always present) |
mediaType | anime or manga. (always present) |
title | Main title. (always present) |
url | Detail-page URL. (always present) |
type | TV, Movie, Manga, and so on. On chart rows without details the count is included, for example TV (12 eps). (most rows) |
score | Weighted community score. (when scored) |
members | Member count; present on ranking-chart listing rows even without details, and on every enriched record. (chart rows, details) |
scoredBy | Number of users behind the weighted score. (details) |
reviewCount | Total review count shown on the entry. (details) |
reviews | Review text, author, date, recommendation, rating, URL, reader reaction total (reactionCount) and reaction breakdown (reactions); three previews by default or more with maxReviews. (details) |
reviewsFetched | Number of reviews actually returned. (details) |
reviewsComplete | True only when the review pages reached their end. (details) |
reviewPagesFetched | Dedicated review pages successfully read; zero with the default previews. (details) |
reviewCountGap | Reported total minus reviews available in the pages; null for a capped or interrupted pull. (complete review pulls) |
characters | Character previews with role and nested voiceActors where available. (details) |
voiceActors | Flat list of voice actors from the character previews. (anime details) |
staff | Staff previews with name and role. (anime details) |
relatedEntries | Related anime and manga with relationship, title and URL. (details) |
openingThemes / endingThemes | Opening and ending song names. (anime details) |
genres / themes | Genre and theme lists. (details) |
synopsis | Full description text. (details) |
changeType | NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. (incremental) |
firstSeenAt | First time this actor saw the record. (incremental) |
lastSeenAt | Most recent time a run saw the record present (on an EXPIRED row, the last time before it disappeared). (incremental) |
changedFields | Field names that differ from the previous run; populated only when changeType is UPDATED. (incremental) |
URL shapes
In Paste URLs mode every link below is understood. Detail and reviews links return one full record; search, chart, genre, season and studio links return their listed records (capped by Maximum items, enriched when Fetch full details is on).
| Shape | Example | Returns |
|---|---|---|
| Anime detail, with slug | myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood | One record |
| Anime detail, bare id | myanimelist.net/anime/5114 | One record |
| Manga detail, with slug or bare id | myanimelist.net/manga/2/Berserk, myanimelist.net/manga/2 | One record |
Reviews page (anime or manga, any ?p=) | myanimelist.net/anime/5114/x/reviews?p=2 | The title's record; reviews follow Maximum reviews |
| Keyword search (anime or manga) | myanimelist.net/anime.php?q=Frieren&cat=anime | Matching records, walked page by page; extra filters such as type and a show offset are kept |
| Top chart (anime or manga) | myanimelist.net/topanime.php?type=airing&limit=50 | Ranked records from that offset; type and limit are kept |
| Genre listing | myanimelist.net/anime/genre/1/Action | Records of the genre, page by page |
| Season (current or year/season) | myanimelist.net/anime/season/2024/fall | Every record of the season |
| Studio / producer | myanimelist.net/anime/producer/1/Studio_Pierrot | Records of the studio |
The mobile host m.myanimelist.net is mapped to the main site. Any other link is skipped with a warning in the log, never silently.
Default URL list. If you leave MyAnimeList URLs untouched in Paste URLs mode, the run reads the example list above (one link per shape) instead of failing; Maximum items still caps the total. Replace the list with your own links to scrape only those.
Rival-compatible fields
Every record also carries malId, rank, titleSynonyms, airedFrom and airedTo (ISO dates), season, year, trailerUrl (detail pages) and scrapedAt. They are derived from data already fetched and add no request. In incremental mode every one of them except rank is left out of change detection rank is the chart position on chart rows and is never replaced by the detail page; it is mirrored from ranked (the overall score rank) only on search and detail rows that have no chart position. A chart position move counts as UPDATED.
Output views
The dataset has four views: Results (every record, union of listing and detail columns), Detail (full title pages: synopsis, stats, credits, related entries, characters, staff, themes), Reviews (one row per review; the review's own url and rating replace the title's in this view) and Changes (what changed since the previous run, for incremental monitoring). A run summary is also saved under the OUTPUT key.
How to Use
- Pick a Collection mode: keyword search, a ranking chart, or pasted URLs.
- Choose anime or manga and enter your keywords, chart or links.
- Set Maximum records, and turn Fetch full details off if listing fields are enough.
- Run it and download the dataset, or read it through the API.
Search walks every result page forward; charts walk the ranking; URL mode reads the links you paste.
Search anime by keyword:
{"mode": "search","mediaType": "anime","searchTerms": ["space opera"],"maxItems": 50,"fetchDetails": true}
Currently airing chart, listing fields only:
{"mode": "charts","mediaType": "anime","chartKind": "airing","maxItems": 100,"fetchDetails": false}
Paste links of both kinds in one run:
{"mode": "url","urls": ["https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood","https://myanimelist.net/manga/2/Berserk"],"maxReviews": 0}
Recurring incremental monitoring of one chart:
{"mode": "charts","mediaType": "manga","chartKind": "top","maxItems": 100,"incrementalMode": true}
A capped chart walk like this one reports NEW, UPDATED and REAPPEARED titles, but never EXPIRED ones: emitExpired only fires after a run that walked every page to the natural end, with no Maximum records or Maximum pages cap stopping it first.
A genuinely empty search is reported honestly as an empty result, never as a failure. Profile pages (user lists) are not scraped: they are account-scoped.
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/myanimelist-scraper").call(run_input={"mode": "search", "searchTerms": ["Frieren"]})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item.get("score"))
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/myanimelist-scraper').call({ mode: 'search', searchTerms: ['Frieren'] });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) continues one interrupted run: paste its run or dataset id and the actor skips every record id it already collected, so you do not pay twice. A resumed run never marks anythingEXPIRED. - Incremental mode (
incrementalMode) is for scheduled runs over the same scope. Each record is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEAREDorEXPIRED(only after a run that walked every page of every scope to its natural end, and only withemitExpired).stateKeynames or shares the stored state. Change detection compares every output field except the bookkeeping keys, the fields that are always left out (reviews.reactionCount,reviews.reactions,malId,titleSynonyms,airedFrom,airedTo,season,year,trailerUrlandscrapedAt) and the fields you list inignoreFieldsForChanges; whole-number values compare equal whether written 25 or 25.0. With incremental mode off, output is exactly as before. - Ignore fields when detecting changes (
ignoreFieldsForChanges, incremental mode only) lists fields that must not count as a change, such as a fast-moving counter. Use dotted paths for nested fields (lists are searched element by element). The always-left-out fields listed above are ignored without you naming them. Ignored fields stay in the output; they are only left out of change detection andchangedFields. Changing this list never causes a one-time wave of UPDATED rows. - One run shares one "already returned" list across all its keywords. A keyword's walk treats a page made up only of titles this run already returned as the end of its results, once that keyword has returned at least one new title on an earlier page. So when keywords in the same
searchTermslist overlap, a later keyword can stop early and skip its own later pages, even though those pages still hold titles no keyword has returned yet. This is rare for unrelated keywords, but likely for near-duplicate ones (for example"Attack on Titan"and"Attack on Titan Season 2"in the same run). WithincrementalModeandemitExpiredon, that early stop can also mark a title that is still on MyAnimeList asEXPIRED: if it sat only on a skipped page, the run counts it as gone. The same rule applies to a resumed run: if the ranking shifted since the interrupted run (common on the airing and most-popular charts), a page of already-collected titles can end the resumed walk before the pages it still needed. - Workaround for a guaranteed-complete scan: put each near-duplicate keyword in its own run, and give each run its own incremental state (leave
stateKeyempty, or use a differentstateKeyper run). Never reuse onestateKeyfor runs with different keywords: each complete run would mark the other run's titlesEXPIRED. If a resumed run looks short, start a fresh run instead.
Send results into your apps (MCP connectors)
After a run, results can also be piped into your apps: mcpConnectors names the connector ids, notionParentPageUrl sets the Notion parent page, and maxNotifyListings caps items per connector (default 50, dataset unchanged). Connector export needs the connector authorized in Apify; the dataset is written regardless.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | "search" | Keyword search, Ranking charts, or Paste URLs. |
mediaType | string | "anime" | Anime, manga or both (search and charts; URL mode auto-detects). Anime and manga ids are separate numbering, so with both a manga row is kept even when an anime row has the same number. |
searchTerms | array | ["Frieren"] | Keywords; each is its own walk, merged and de-duplicated. |
searchType | string | "" | MyAnimeList's own type filter for keyword search (TV, OVA, movie, special, ONA, music for anime; manga, novel, one-shot, doujinshi, manhwa, manhua for manga). |
searchQueries | array | none | Alias of searchTerms; both lists are merged. When an API call sets only searchQueries, animeIds, mangaIds or topType, the shipped sample term Frieren is not run next to it. |
chartKind | string | "top" | top, airing, upcoming, bypopularity or favorite. |
topType | string | "" | Shortcut for the Top ranking chart of anime or manga (empty, anime or manga). |
topLimit | integer | 0 | With topType: how many ranked titles. It sets the item cap while maxItems is left at its default of 20; any other maxItems value wins. 0 uses maxItems. |
urls | array | one example per link shape | Links to read directly: detail, reviews, search, chart, genre, season and studio pages (see URL shapes). Default: one example of each shape; that untouched default list is not run next to animeIds, mangaIds, searchQueries or topType. |
animeIds | array | none | MyAnimeList ids read as detail pages, alone or on top of the selected mode (counted by the same Maximum items cap). |
mangaIds | array | none | MyAnimeList ids read as detail pages, alone or on top of the selected mode (counted by the same Maximum items cap). |
fetchDetails | boolean | true | Read every record's own page (adds the detail-enrichment surcharge). |
maxReviews | integer | 3 | Reviews per record: 3 previews by default, a larger finite limit, or 0 for all available pages up to 5000 reviews. Requires detail fetching; large histories take longer. |
maxItems | integer | 20 | The one finite cap (default 20). 0 means no limit. |
maxPages | integer | 0 | Pages per scope. 0 (default) walks to the natural end. |
proxy | object | {"useApifyProxy": true} | Optional connection settings. |
resumeFromRunId | string | none | Previous run or dataset id; the run returns only new records. |
incrementalMode | boolean | false | Classify changes across scheduled runs of the same scope. |
stateKey | string | none | Optional campaign name for the incremental baseline. |
emitUnchanged | boolean | false | Also return unchanged records (bills extra rows). |
emitExpired | boolean | false | Also return records no longer found, after a complete scan (bills extra rows). |
ignoreFieldsForChanges | array | none | Fields (dotted paths for nested ones) left out of change detection; incremental mode only. |
mcpConnectors | array | none | Connector ids to also export results into. |
notionParentPageUrl | string | none | Parent page for the Notion export. |
maxNotifyListings | integer | 50 | Maximum items per connector export. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
The dataset holds one record per row; the overview view shows the headline columns. Fictional sample:
{"id": 123456,"mediaType": "anime","title": "Sample Anime: Legend of the Test Fields","type": "TV","episodes": 12,"score": 8.61,"scoredBy": 4200,"ranked": 114,"members": 1234567,"reviewCount": 12,"reviews": [{"author": "sample_user", "date": "Jan 1, 2026", "recommendation": "Recommended", "rating": 9, "text": "An illustrative review preview."}],"reviewsFetched": 1,"reviewsComplete": false,"reviewPagesFetched": 0,"reviewCountGap": null,"characters": [{"id": 100001, "name": "Sample Character", "role": "Main", "voiceActors": [{"id": 200001, "name": "Sample Performer", "language": "Japanese"}]}],"voiceActors": [{"id": 200001, "name": "Sample Performer", "language": "Japanese", "characterId": 100001}],"relatedEntries": [{"id": 100002, "mediaType": "manga", "title": "Sample Source Manga", "relation": "Adaptation"}],"staff": [{"id": 200002, "name": "Sample Director", "role": "Director"}],"openingThemes": ["Sample Opening"],"endingThemes": ["Sample Ending"],"genres": ["Action", "Adventure"],"studios": ["Sample Studio"],"synopsis": "A sample synopsis body.","url": "https://myanimelist.net/anime/123456/Sample_Anime","changeType": "NEW","changedFields": [],"firstSeenAt": "2026-01-01T00:00:00Z","lastSeenAt": "2026-01-01T00:00:00Z"}
Plan Requirement
An Apify account is required to run this actor. Measured on this site: the standard Apify datacenter proxy reads MyAnimeList pages fine, so no residential proxy is needed and the default connection settings work on a plan that includes Apify proxy. If the default connection is refused for your account, the actor logs "The selected connection is unavailable to this run. Apify free plans do not include residential proxies." and continues on a backup connection; once that backup serves pages it logs "Served over the backup connection (the default connection was unavailable)." If nothing can be read the run fails with one of these messages:
- "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required." (also check the credentials of any proxy URLs you entered).
- "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested MyAnimeList pages."
- "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."
Each page request has a 25 second budget across retries, so a slow page cannot stall the run.
Pricing and billing
The actor uses pay per event. The Pricing tab shows the current rates; this page does not quote prices. Charged events and when they fire:
- Result record: one per record returned.
- Detail enrichment: one per returned record that was enriched with its own detail page (
fetchDetailson). - Review enrichment: one per review item returned in a record, including the three default previews.
Detail and review events are charged per record, right after the record is saved, not at the end of the run, so a stopped or timed-out run is billed only for the records already delivered. Records suppressed as UNCHANGED, failed pages and unread records are never charged. Turn fetchDetails off for listing fields only (no enrichment events), and use Maximum records to cap any run.
FAQ
How much does it cost?
You pay for each record returned, plus the detail-enrichment and review-enrichment events only when they actually fire (a record you did not enrich, or one suppressed as UNCHANGED, is never charged for either). The Pricing tab on the actor page shows the current rates. Use Maximum records to cap the cost of any run.
Is it legal to scrape MyAnimeList?
This actor collects only publicly available anime and manga data. You are responsible for how you use it: follow MyAnimeList's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Titles, scores and rankings are largely factual catalogue data, but review text is authored by MyAnimeList users, and character or key art images may carry separate rights.
Can I get only new or updated titles on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then classifies every record against the last run's baseline for the same scope, and unchanged records are not billed unless you turn on Emit unchanged records. See "Resume and recurring updates" above for the one caveat: overlapping keywords in one run can end a keyword's walk early and, with Emit expired records on, mark a still-listed title EXPIRED. Put near-duplicate keywords in separate runs, each with its own state, and never reuse one stateKey across runs with different keywords.
Why did a search or chart return fewer titles than I expected?
Three separate reasons produce a short result, and only one of them is a cap: Maximum records or Maximum pages per keyword or chart stopped the walk on purpose; the search genuinely has no more matches (MyAnimeList answers a search with no more rows the same way it answers a search with no rows at all); or, for a run with more than one keyword in searchTerms or a resumed run, the shared "already returned" caveat above cut a walk short. Raise the caps, broaden the keyword, or split near-duplicate keywords into separate runs.
Why did my run fail instead of returning an empty dataset?
A run with no results fails, with a clear connection-problem message, only when not a single page could be read, so "no titles matched" is never confused with "nothing could be read". Run it again in a few minutes. A run also stops at the start, before anything is collected or charged, when the input cannot work: an unreadable resumeFromRunId, or resumeFromRunId combined with incremental mode on a scope that already has saved state. If only some keywords, charts or URLs could not be read, you still get what was found, with a status message naming how many.
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:
| ๐งฉ AniList Anime & Manga Scraper Scrape AniList anime and manga: titles (romaji/English/native), scores, popularity... | ๐งฉ WEBTOON Scraper Scrape the WEBTOON catalog into structured data. Extract series, genres, rankings and... |
| ๐งฉ PineDrama Scraper Scrape Pine Drama series by keyword, category or URL across 17 languages. Extract titles... | ๐งฉ GoodShort Scraper Scrape the GoodShort short-drama catalog: titles with exact views, follows, genres and... |
| ๐งฉ ShortMax Scraper Scrape the ShortMax short-drama catalog: titles, descriptions, creators, view and follow... | ๐งฉ ReelShort Scraper Scrape the ReelShort vertical short-drama catalog: titles, synopses, themes and full tag... |
๐ 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.