# MyAnimeList Scraper - Anime, Manga, Rankings & Scores (`abotapi/myanimelist-scraper`) Actor

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.

- **URL**: https://apify.com/abotapi/myanimelist-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 anime or manga records

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

## MyAnimeList Scraper

### Why This Scraper?

- Walks MyAnimeList search results forward through every page, not just page 1.
- Covers all five ranking charts (top, airing, upcoming, most popular, most favourited) for anime and manga.
- Enriches records with related entries, character and staff previews, voice actors, paginated reviews and full stats.
- Reads pasted detail-page links, anime and manga mixed, auto-detected.
- Resume from a previous run and incremental monitoring are built in.
- Keeps the main dataset to one row per anime or manga, including nested review and preview lists.
- Pushes each record the moment it is ready, so a stopped run keeps its data.

### Data You Get

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 every
available review page. `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 title, manga volumes and chapters,
synonyms, favorites, licensors, producers, demographics, serialization,
premiere, broadcast, source, duration, rating and review sentiment counts
(`reviewBreakdown`).

| Field | Always | Notes |
|---|---|---|
| `id` | yes | MyAnimeList's numeric id. |
| `mediaType` | yes | anime or manga. |
| `title` | yes | Main title. |
| `url` | yes | Detail-page URL. |
| `type` | most rows | TV, Movie, Manga, and so on. |
| `score` | when scored | Weighted community score. |
| `members` | details | Member count. |
| `scoredBy` | details | Number of users behind the weighted score. |
| `reviewCount` | details | Total review count shown on the entry. |
| `reviews` | details | Review text, author, date, recommendation, rating and URL; three previews by default or more with `maxReviews`. |
| `reviewsFetched` | details | Number of reviews actually returned. |
| `reviewsComplete` | details | True only when the review pages reached their end. |
| `reviewPagesFetched` | details | Dedicated review pages successfully read; zero with the default previews. |
| `reviewCountGap` | complete review pulls | Reported total minus reviews available in the pages; null for a capped or interrupted pull. |
| `characters` | details | Character previews with role and nested `voiceActors` where available. |
| `voiceActors` | anime details | Flat list of voice actors from the character previews. |
| `staff` | anime details | Staff previews with name and role. |
| `relatedEntries` | details | Related anime and manga with relationship, title and URL. |
| `openingThemes` | anime details | Opening song names. |
| `endingThemes` | anime details | Ending song names. |
| `genres` | details | Genre list. |
| `themes` | details | Theme list. |
| `synopsis` | details | Full description text. |
| `changeType` | incremental | NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. |
| `firstSeenAt` | incremental | First time this actor saw the record. |

### How to Use

Pick a mode, set the scope, run. Search walks every result page forward;
charts walk the ranking; URL mode reads the links you paste. Example 1,
anime search with details:

```json
{
  "mode": "search",
  "mediaType": "anime",
  "searchTerms": ["space opera"],
  "maxItems": 50,
  "fetchDetails": true
}
```

Example 2, the currently-airing chart, listing fields only:

```json
{
  "mode": "charts",
  "mediaType": "anime",
  "chartKind": "airing",
  "maxItems": 100,
  "fetchDetails": false
}
```

Example 3, pasted links of both kinds in one run:

```json
{
  "mode": "url",
  "urls": [
    "https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood",
    "https://myanimelist.net/manga/2/Berserk"
  ],
  "maxReviews": 0
}
```

Example 4, recurring incremental monitoring of one chart:

```json
{
  "mode": "charts",
  "mediaType": "manga",
  "chartKind": "top",
  "maxItems": 100,
  "incrementalMode": true,
  "emitExpired": true
}
```

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.

### Input Parameters

| Input | What it does |
|---|---|
| `mode` | Keyword search, Ranking charts, or Paste URLs. |
| `mediaType` | Anime or manga (search and charts; URL mode auto-detects). |
| `searchTerms` | Keywords; each is its own walk, merged and de-duplicated. |
| `chartKind` | top, airing, upcoming, bypopularity or favorite. |
| `urls` | Detail-page links to read directly. |
| `fetchDetails` | Read every record's own page (adds the detail-enrichment surcharge). |
| `maxReviews` | Reviews per record: 3 previews by default, a larger finite limit, or 0 for all available pages. Requires detail fetching; large histories take longer. |
| `maxItems` | The one finite cap (default 20). 0 means no limit. |
| `maxPages` | Pages per scope. 0 (default) walks to the natural end. |
| `resumeFromRunId` | Previous run or dataset id; the run returns only new records. |
| `incrementalMode` | Classify changes across scheduled runs of the same scope. |
| `stateKey` | Optional campaign name for the incremental baseline. |
| `emitUnchanged` | Also return unchanged records (bills extra rows). |
| `emitExpired` | Also return records no longer found, after a complete scan (bills extra rows). |
| `proxy` | Optional connection settings. |
| `mcpConnectors` | Connector ids to also export results into. |
| `notionParentPageUrl` | Parent page for the Notion export. |
| `maxNotifyListings` | Maximum items per connector export. |

### Output Example

The dataset holds one record per row; the overview view shows the headline
columns. Fictional sample:

```json
{
  "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"
}
```

### Plan Requirement

An Apify account is required to run this actor. Detail enrichment adds a
per-record charge only when an enriched record is returned. Each review in
a returned record adds one review-enrichment event, including the three
default previews. The review event is priced per review item.

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

# Actor input Schema

## `mode` (type: `string`):

Search MyAnimeList by keyword, walk a ranking chart, or read detail pages you paste.

## `mediaType` (type: `string`):

Applies to search and charts. URL mode detects anime or manga from each URL.

## `searchTerms` (type: `array`):

One or more keywords. Each keyword is its own walk; results are de-duplicated across keywords.

## `chartKind` (type: `string`):

Which ranking chart to walk in Charts mode.

## `urls` (type: `array`):

Detail-page links, e.g. myanimelist.net/anime/5114/... or myanimelist.net/manga/2/... Bare /anime/<id> links also work.

## `fetchDetails` (type: `boolean`):

Adds synopsis, full stats, related entries, character and staff previews, voice actors, and three review previews from each record's page. Use Maximum reviews to collect more. Adds a per-record detail-enrichment surcharge (see Output).

## `maxReviews` (type: `integer`):

3 (default) uses title-page previews with no extra review-page requests. Set a larger number to collect that many reviews, or 0 to follow all available review pages. Applies only when details are fetched; each returned review, including a preview, adds one review-enrichment event.

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

Stop after this many records across all keywords or links. 0 means no limit: the run ends at the natural end of results.

## `maxPages` (type: `integer`):

Pages to walk per keyword or chart. 0 (default) keeps walking until the item cap or the natural end of results; Max records remains the only cap that stops a run early.

## `resumeFromRunId` (type: `string`):

Paste a previous run id (or dataset id) to skip the records it already collected and return only new ones.

## `incrementalMode` (type: `boolean`):

For scheduled runs of the same scope: classify each record as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against the previous run's baseline. Records whose content did not change are suppressed unless Emit unchanged is on.

## `stateKey` (type: `string`):

Stable name for a monitoring campaign. Leave empty to key the baseline automatically on the mode, media type and scope.

## `emitUnchanged` (type: `boolean`):

With incremental mode on, also return records whose content did not change, marked UNCHANGED. These are extra rows: they are returned AND billed.

## `emitExpired` (type: `boolean`):

With incremental mode on, also return records no longer found, marked EXPIRED. Only after a complete uncapped scan of the scope; these are extra rows: they are returned AND billed.

## `proxy` (type: `object`):

Use the default connection settings, or adjust them for your run.

## `mcpConnectors` (type: `array`):

Connector ids to also export results into after the run. Dataset output is unchanged.

## `notionParentPageUrl` (type: `string`):

Parent page for the Notion connector export.

## `maxNotifyListings` (type: `integer`):

Maximum items sent to each connector. Does not change the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "mediaType": "anime",
  "searchTerms": [
    "Frieren"
  ],
  "chartKind": "top",
  "urls": [
    "https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood"
  ],
  "fetchDetails": true,
  "maxReviews": 3,
  "maxItems": 20,
  "maxPages": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "mode": "search",
    "mediaType": "anime",
    "searchTerms": [
        "Frieren"
    ],
    "chartKind": "top",
    "urls": [
        "https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood"
    ],
    "fetchDetails": true,
    "maxReviews": 3,
    "maxItems": 20,
    "maxPages": 0,
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    },
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/myanimelist-scraper").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 = {
    "mode": "search",
    "mediaType": "anime",
    "searchTerms": ["Frieren"],
    "chartKind": "top",
    "urls": ["https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood"],
    "fetchDetails": True,
    "maxReviews": 3,
    "maxItems": 20,
    "maxPages": 0,
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/myanimelist-scraper").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 '{
  "mode": "search",
  "mediaType": "anime",
  "searchTerms": [
    "Frieren"
  ],
  "chartKind": "top",
  "urls": [
    "https://myanimelist.net/anime/5114/Fullmetal_Alchemist__Brotherhood"
  ],
  "fetchDetails": true,
  "maxReviews": 3,
  "maxItems": 20,
  "maxPages": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}' |
apify call abotapi/myanimelist-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/myanimelist-scraper"
        }
    }
}
```

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/W66LQWzgpo4FronDe/builds/m71v504JpUB17AU7H/openapi.json
