MyAnimeList Scraper - Anime, Manga, Rankings & Scores avatar

MyAnimeList Scraper - Anime, Manga, Rankings & Scores

Pricing

from $1.20 / 1,000 anime or manga records

Go to Apify Store
MyAnimeList Scraper - Anime, Manga, Rankings & Scores

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

Abot API

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

14 days ago

Last modified

Categories

Features

Limited permissions

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).

FieldExample
idMyAnimeList's numeric id. (always present)
mediaTypeanime or manga. (always present)
titleMain title. (always present)
urlDetail-page URL. (always present)
typeTV, Movie, Manga, and so on. On chart rows without details the count is included, for example TV (12 eps). (most rows)
scoreWeighted community score. (when scored)
membersMember count; present on ranking-chart listing rows even without details, and on every enriched record. (chart rows, details)
scoredByNumber of users behind the weighted score. (details)
reviewCountTotal review count shown on the entry. (details)
reviewsReview text, author, date, recommendation, rating, URL, reader reaction total (reactionCount) and reaction breakdown (reactions); three previews by default or more with maxReviews. (details)
reviewsFetchedNumber of reviews actually returned. (details)
reviewsCompleteTrue only when the review pages reached their end. (details)
reviewPagesFetchedDedicated review pages successfully read; zero with the default previews. (details)
reviewCountGapReported total minus reviews available in the pages; null for a capped or interrupted pull. (complete review pulls)
charactersCharacter previews with role and nested voiceActors where available. (details)
voiceActorsFlat list of voice actors from the character previews. (anime details)
staffStaff previews with name and role. (anime details)
relatedEntriesRelated anime and manga with relationship, title and URL. (details)
openingThemes / endingThemesOpening and ending song names. (anime details)
genres / themesGenre and theme lists. (details)
synopsisFull description text. (details)
changeTypeNEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. (incremental)
firstSeenAtFirst time this actor saw the record. (incremental)
lastSeenAtMost recent time a run saw the record present (on an EXPIRED row, the last time before it disappeared). (incremental)
changedFieldsField 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).

ShapeExampleReturns
Anime detail, with slugmyanimelist.net/anime/5114/Fullmetal_Alchemist__BrotherhoodOne record
Anime detail, bare idmyanimelist.net/anime/5114One record
Manga detail, with slug or bare idmyanimelist.net/manga/2/Berserk, myanimelist.net/manga/2One record
Reviews page (anime or manga, any ?p=)myanimelist.net/anime/5114/x/reviews?p=2The title's record; reviews follow Maximum reviews
Keyword search (anime or manga)myanimelist.net/anime.php?q=Frieren&cat=animeMatching 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=50Ranked records from that offset; type and limit are kept
Genre listingmyanimelist.net/anime/genre/1/ActionRecords of the genre, page by page
Season (current or year/season)myanimelist.net/anime/season/2024/fallEvery record of the season
Studio / producermyanimelist.net/anime/producer/1/Studio_PierrotRecords 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

  1. Pick a Collection mode: keyword search, a ranking chart, or pasted URLs.
  2. Choose anime or manga and enter your keywords, chart or links.
  3. Set Maximum records, and turn Fetch full details off if listing fields are enough.
  4. 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 ApifyClient
client = 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 anything EXPIRED.
  • Incremental mode (incrementalMode) is for scheduled runs over the same scope. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that walked every page of every scope to its natural end, and only with emitExpired). stateKey names 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, trailerUrl and scrapedAt) and the fields you list in ignoreFieldsForChanges; 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 and changedFields. 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 searchTerms list 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). With incrementalMode and emitExpired on, that early stop can also mark a title that is still on MyAnimeList as EXPIRED: 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 stateKey empty, or use a different stateKey per run). Never reuse one stateKey for runs with different keywords: each complete run would mark the other run's titles EXPIRED. 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

ParameterTypeDefaultDescription
modestring"search"Keyword search, Ranking charts, or Paste URLs.
mediaTypestring"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.
searchTermsarray["Frieren"]Keywords; each is its own walk, merged and de-duplicated.
searchTypestring""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).
searchQueriesarraynoneAlias 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.
chartKindstring"top"top, airing, upcoming, bypopularity or favorite.
topTypestring""Shortcut for the Top ranking chart of anime or manga (empty, anime or manga).
topLimitinteger0With 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.
urlsarrayone example per link shapeLinks 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.
animeIdsarraynoneMyAnimeList ids read as detail pages, alone or on top of the selected mode (counted by the same Maximum items cap).
mangaIdsarraynoneMyAnimeList ids read as detail pages, alone or on top of the selected mode (counted by the same Maximum items cap).
fetchDetailsbooleantrueRead every record's own page (adds the detail-enrichment surcharge).
maxReviewsinteger3Reviews 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.
maxItemsinteger20The one finite cap (default 20). 0 means no limit.
maxPagesinteger0Pages per scope. 0 (default) walks to the natural end.
proxyobject{"useApifyProxy": true}Optional connection settings.
resumeFromRunIdstringnonePrevious run or dataset id; the run returns only new records.
incrementalModebooleanfalseClassify changes across scheduled runs of the same scope.
stateKeystringnoneOptional campaign name for the incremental baseline.
emitUnchangedbooleanfalseAlso return unchanged records (bills extra rows).
emitExpiredbooleanfalseAlso return records no longer found, after a complete scan (bills extra rows).
ignoreFieldsForChangesarraynoneFields (dotted paths for nested ones) left out of change detection; incremental mode only.
mcpConnectorsarraynoneConnector ids to also export results into.
notionParentPageUrlstringnoneParent page for the Notion export.
maxNotifyListingsinteger50Maximum 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 (fetchDetails on).
  • 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.

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.