AniList Scraper: Anime, Manga & Studio Data avatar

AniList Scraper: Anime, Manga & Studio Data

Pricing

from $1.00 / 1,000 title scrapeds

Go to Apify Store
AniList Scraper: Anime, Manga & Studio Data

AniList Scraper: Anime, Manga & Studio Data

Scrape AniList via GraphQL: anime and manga titles, scores, popularity, genres, studios, staff, airing schedules and relations. Rich metadata for media apps.

Pricing

from $1.00 / 1,000 title scrapeds

Rating

0.0

(0)

Developer

Arman Hossain

Arman Hossain

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

5 hours ago

Last modified

Share

AniList Scraper — Anime and manga metadata — scores, popularity, genres, studios and airing dates

AniList Scraper pulls structured anime and manga metadata straight from the AniList GraphQL API, titles in three scripts, scores, popularity, favourites, genres, community tags, studios, airing dates and full synopses.

Give it a list of search terms, or skip search entirely and browse a whole season by genre. Either way you get one clean dataset row per title. No proxy setup, no browser, no credentials to manage.

What you get

Output fieldMeaning
idAniList media ID, stable, use it as your join key
titleRomaji, titleEnglish, titleNativeAll three official title forms. titleEnglish is null when AniList has no licensed English title
typeANIME or MANGA
formatTV, MOVIE, OVA, ONA, SPECIAL, MANGA, NOVEL, ONE_SHOT
statusFINISHED, RELEASING, NOT_YET_RELEASED, CANCELLED, HIATUS
episodes, chaptersEpisode count for anime, chapter count for manga, the other is null
averageScoreWeighted community score out of 100
popularity, favouritesUsers with the title on a list, and users who favourited it
genresAniList's curated genre list
tagsCommunity tags, ranked most-relevant first
studiosProducing studios, main studio first
startDate, endDateYYYY-MM-DD, degrading to YYYY-MM or YYYY when AniList only knows part of the date
seasonAiring season and year, e.g. SPRING 2013
coverImageHighest-resolution cover art URL
descriptionSynopsis as clean plain text, AniList's stray <br> and <i> tags stripped
scrapedAtRun timestamp

A RUN_SUMMARY record in the key-value store holds per-run counts, per-source counts, the filters applied, the number of API requests spent and any query that failed.

Input

FieldTypeDefaultNotes
searchTermsarray[]Title searches, one query each, ranked by relevance. Empty = browse using the filters below.
mediaTypestringANIMEANIME or MANGA.
seasonstring-WINTER, SPRING, SUMMER or FALL. Anime only.
seasonYearinteger-Airing year, e.g. 2024.
genresarray[]Exact AniList genre names. A title must carry every genre listed.
maxResultsinteger100Total titles saved across the run. Split evenly between search terms.

Which combinations make sense

  • searchTerms alone, the fastest way to enrich a known list of titles.
  • season + seasonYear with no searchTerms, the seasonal chart, most popular first. This is the mode to schedule.
  • genres narrows either mode. Genres are ANDed, so ["Action", "Fantasy"] returns only titles carrying both.
  • season without seasonYear matches that season in every year, usually not what you want.

Example input

{
"searchTerms": ["attack on titan", "cowboy bebop"],
"mediaType": "ANIME",
"genres": ["Action"],
"maxResults": 12
}

Output

A real record from the run above, abridged in the long fields:

{
"id": 16498,
"titleRomaji": "Shingeki no Kyojin",
"titleEnglish": "Attack on Titan",
"titleNative": "進撃の巨人",
"type": "ANIME",
"format": "TV",
"status": "FINISHED",
"episodes": 25,
"chapters": null,
"averageScore": 85,
"popularity": 1038684,
"favourites": 85824,
"genres": ["Action", "Drama", "Fantasy", "Mystery"],
"tags": ["Kaiju", "Revenge", "Tragedy", "Military", "Henshin", "…"],
"studios": ["WIT STUDIO", "Pony Canyon", "Kodansha", "Production I.G", "…"],
"startDate": "2013-04-07",
"endDate": "2013-09-28",
"season": "SPRING 2013",
"coverImage": "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx16498-buvcRTBx4NSm.jpg",
"description": "Several hundred years ago, humans were nearly exterminated by titans. …",
"scrapedAt": "2026-08-06T11:29:28.483Z"
}

RUN_SUMMARY:

{
"sourcesRequested": 2,
"sourcesFailed": 0,
"failures": [],
"titlesSaved": 9,
"titlesPerSource": { "attack on titan": 6, "cowboy bebop": 3 },
"apiRequests": 2,
"rateLimitPerMin": 30,
"filters": {
"searchTerms": ["attack on titan", "cowboy bebop"],
"mediaType": "ANIME",
"season": null,
"seasonYear": null,
"genres": ["Action"],
"maxResults": 12
},
"finishedAt": "2026-08-06T11:29:30.148Z"
}

Use cases

1. Build an anime tracking app. Seed your catalogue with the current season, then re-run weekly to pick up score and episode-count changes.

{
"mediaType": "ANIME",
"season": "SPRING",
"seasonYear": 2024,
"maxResults": 300
}

2. Analyse seasonal release trends. Run the same query across seasons and compare studio output, genre mix and average scores. Change season/seasonYear per run and diff on id.

{
"mediaType": "ANIME",
"season": "FALL",
"seasonYear": 2024,
"genres": ["Action"],
"maxResults": 200
}

3. Media licensing research. Pull manga by genre with chapter counts, status and publisher studios to find completed series with high favourites-to-popularity ratios.

{
"mediaType": "MANGA",
"genres": ["Psychological", "Thriller"],
"maxResults": 150
}

Limits and behaviour

  • GraphQL POST, fixed query. Every request asks for the same field set, so 50 titles cost exactly one request regardless of filters.
  • Self-pacing rate limiter. AniList advertises its budget in rate-limit headers and the Actor reads it from the first response, then spaces requests to match. It currently advertises 30 requests/minute; AniList's documentation still describes 90/min, so the Actor trusts the header rather than the docs. A 429 is honoured via retry-after.
  • Null filters are omitted, not sent. AniList applies an explicit null variable as a literal filter, season: null matches only titles with no season and returns nothing. Unset filters are dropped from the variables object entirely.
  • maxResults is a total, split evenly. With two search terms and maxResults: 12, each term gets a budget of 6. A term that has fewer matches simply returns fewer; the leftover is not redistributed.
  • AniList caps pageInfo.total at 5000 for broad browse queries, so treat it as "at least 5000", not an exact count. Page size is capped at 50 server-side.
  • A failing query never aborts the run. It is logged, recorded in RUN_SUMMARY.failures, and the next source proceeds. The Actor only errors out if every source fails.
  • Transient errors are retried. 429 and 5xx get three attempts with linear backoff. GraphQL validation errors fail fast, because retrying a malformed query never helps.
  • Public data only. No authentication, no personal data, no access-control bypass. AniList's content is user-contributed and licensed for reuse.

FAQ

Do I need a proxy? No. Proxy configuration is not required to run this Actor.

Do I need an AniList account or API key? No. You supply no credentials.

What happens if AniList is unavailable? The failing query is reported in RUN_SUMMARY.failures and the run continues with the next source. The run only fails outright if every source failed.

Can I schedule it? Yes, it is designed for scheduled runs. Weekly seasonal sweeps are the most common pattern; diff on id plus averageScore to catch score drift.

Why is titleEnglish sometimes null? AniList only carries an English title when one has been officially licensed. Fall back to titleRomaji, which is always present.

Why did a search return fewer titles than I asked for? Either the search has few matches, or your genres filter excluded the rest, genres are ANDed. RUN_SUMMARY.titlesPerSource shows the count for each term so you can tell the two apart.

Can I get staff and character data? Not in this Actor. The query shape is deliberately fixed so per-title cost stays constant; staff and character edges would multiply request volume per title.

Can I integrate it with something else? Yes, Apify API, client libraries, webhooks, scheduled runs, dataset exports (JSON/CSV/Excel) or MCP. Output is structured JSON.

API example

curl -X POST "https://api.apify.com/v2/acts/arman-bd~anilist-anime-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mediaType": "ANIME",
"season": "SPRING",
"seasonYear": 2024,
"maxResults": 75
}'

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/anilist-anime-scraper').call({
searchTerms: ['frieren', 'chainsaw man'],
mediaType: 'ANIME',
maxResults: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const t of items) console.log(`${t.titleEnglish ?? t.titleRomaji}, ${t.averageScore} (${t.season})`);