# Kitsu Anime Manga Scraper (`b2b_lead_generation/kitsu-anime-manga-scraper`) Actor

Search the Kitsu catalog for any anime or manga and get one clean row per title — slug, synopsis, rating, popularity rank, dates, and more. Search by title, pull trending anime, or look up titles by id. Export to JSON, CSV, or Excel. Auto-retries, skips duplicates, and runs without an account

- **URL**: https://apify.com/b2b_lead_generation/kitsu-anime-manga-scraper.md
- **Developed by:** [B2B Lead Generation](https://apify.com/b2b_lead_generation) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

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

## Kitsu Anime & Manga Scraper: Anime and manga search

<p align="center">
  <img src="https://i.imgur.com/IkNylDs.jpeg" alt="Kitsu Anime & Manga Scraper" style="max-width:100%; border-radius:14px; width:680px;" />
</p>

Kitsu Anime & Manga Scraper searches the public Kitsu catalog and saves one dataset row per anime or manga title. Export the run as JSON, CSV, or Excel.

### Use cases

- **Watchlist research**: search a few titles and keep slug, rating, and rank in one table
- **Catalog export**: pull trending anime on a schedule and download CSV
- **Manga lookup**: search Berserk, or request manga id 8, and keep the synopsis with the rest of the attributes
- **Id check**: pass a list of numeric ids and get either the title or a single error row when Kitsu returns 404
- **Shared dataset**: hand the Apify export to someone who does not want to page through Kitsu

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | array | `["naruto"]` | Title text, one per line. Used when trending is off and record ids are empty. |
| `type` | string | `anime` | `anime` or `manga`. Trending only requests anime. |
| `trending` | boolean | `false` | Load trending anime and skip search and ids. |
| `recordIds` | array | empty | Numeric Kitsu ids. Non-numeric values become error rows and are not requested. |
| `maxItems` | integer | `100` | Cap on successful rows. Maximum 1000. |
| `requestDelaySecs` | number | `0.5` | Pause between requests. Minimum 0.5 seconds. |
| `timeoutSecs` | integer | `300` | Stop the run after this many seconds and keep rows already saved. |
| `requestTimeoutSecs` | integer | `30` | Per-request timeout. |
| `proxyConfiguration` | object | `{"useApifyProxy": false}` | Optional. Leave the proxy off unless you need one. |

```json
{
  "searchQueries": ["naruto"],
  "type": "anime",
  "trending": false,
  "recordIds": [],
  "maxItems": 100,
  "requestDelaySecs": 0.5,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

### What data does this actor extract?

Each successful row is one Kitsu resource. The JSON:API `type` field is stored as `mediaType` so the dataset schema stays valid. `attributes` still holds the full object from Kitsu, including the long synopsis.

```json
{
  "id": "1555",
  "mediaType": "anime",
  "slug": "naruto-shippuden",
  "canonicalTitle": "Naruto: Shippuuden",
  "averageRating": "84.06",
  "popularityRank": 28,
  "startDate": "2007-02-15",
  "mode": "anime_search",
  "source_url": "https://kitsu.io/api/edge/anime?filter[text]=naruto&page[limit]=2&page[offset]=0",
  "scraped_at": "2026-10-12T00:00:00+00:00"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Resource id from Kitsu. |
| `mediaType` | string | `anime` or `manga`. |
| `slug` | string | Slug from attributes. |
| `canonicalTitle` | string | Canonical title from attributes. |
| `synopsis` | string | Synopsis from attributes. |
| `averageRating` | string | Rating string from the source. |
| `popularityRank` | integer | Popularity rank, or null. |
| `links` | object | Links object. Relative API paths are made absolute. |
| `attributes` | object | Full attributes object. |
| `relationships` | object | Relationship links. Those URLs are not fetched. |
| `mode` | string | `anime_search`, `manga_search`, `trending`, or `detail`. |
| `source_url` | string | Request URL for the row. |
| `scraped_at` | string | UTC time the row was saved. |
| `error` | string | Set on a failed input, with `input` and `status`. |

A failed id or a bad response is one error row (`error`, `input`, `status`). The run continues with the next input.

### How it works

1. Read the input and pick one mode: trending anime, numeric ids, or title search.
2. Request only the public anime, manga, and trending anime catalog pages, plus a single title looked up by its numeric id.
3. Identify the client politely and wait at least `requestDelaySecs` between calls.
4. On 429, 5xx, or a timeout, wait using Retry-After when it is present, otherwise `2^attempt` seconds (cap 60), up to 5 tries. If a rate-limit remaining header is `0`, wait for the reset value too.
5. Follow `links.next` only when the next page stays within the same anime or manga catalog. List pages request at most 20 rows. Duplicate ids are dropped. The run stops at `maxItems` or `timeoutSecs`.

### FAQ

**How fresh is the data?**
Each run calls Kitsu at request time. `scraped_at` is when that row was saved, not when Kitsu last edited the title. `attributes.updatedAt` is Kitsu's own timestamp when the payload includes it.

**What happens if the search is empty?**
An empty query list, with trending off and no ids, finishes successfully and saves nothing. A search that returns no titles logs a warning and moves on.

**What if an id is wrong?**
A 404 becomes one error row with that id and status. Later ids still run. A slug is not requested, because only numeric ids are supported. It is saved as an error row instead.

**Can I export CSV?**
Yes. Apify datasets export to JSON, CSV, and Excel.

#### Trademark Notice

Kitsu Anime & Manga and related names, logos, and trademarks belong to their respective owners. Their use in this documentation is solely to identify the source of the data and does not imply affiliation, sponsorship, endorsement, or partnership.

#### Disclaimer

Disclaimer: This Actor is an independent tool and is not affiliated with, endorsed by, sponsored by, or otherwise officially associated with Kitsu Anime & Manga or its owners. All data is collected from publicly available sources. Users are responsible for complying with the source's terms of use, rate limits, and attribution or licensing requirements.

#### Is web scraping legal?

This Actor only collects publicly available data from Kitsu Anime & Manga, mostly through its public API or feed, without logging in or bypassing any access controls. Scraping public data is generally legal, but how you use it matters:

- **Personal data:** If the results include personal data (for example names, emails, or profile details), laws such as the GDPR in the EU and the CCPA in California may apply. Only collect and store personal data when you have a legitimate reason.
- **Copyright:** Some content (articles, images, descriptions) may be protected by copyright. Do not republish full copyrighted content without permission.
- **Terms of use:** Respect the source terms, stated rate limits, and any attribution or non-commercial-use requirements listed in Limits and terms.
- **Legal advice:** This is general information, not legal advice. If you're unsure, consult a lawyer.

To learn more, read Apify's guide: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

# Actor input Schema

## `searchQueries` (type: `array`):

Title text for anime or manga search, one title per line. Example: naruto. Ignored when trending is on or record ids are set.

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

Which catalog to query. anime calls the anime search or anime detail URL. manga calls the manga search or manga detail URL. Trending only supports anime.

## `trending` (type: `boolean`):

When checked, load trending anime and skip title search and id lookup. Trending manga is not requested.

## `recordIds` (type: `array`):

Numeric Kitsu ids for one title at a time, using the self URL from search results, such as 1555 for anime. Non-numeric values are saved as error rows and are not requested. Leave empty to search titles.

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

Maximum number of catalog rows to save. The free cap is 1000. Error rows do not count toward this cap.

## `requestDelaySecs` (type: `number`):

Seconds to wait between API calls. Minimum is 0.5 so requests stay sequential.

## `timeoutSecs` (type: `integer`):

Overall time limit for the run, in seconds. The actor stops fetching when this elapses and keeps rows already saved.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for a single API response before retrying.

## `proxyConfiguration` (type: `object`):

Optional proxy for API requests. Leave Apify Proxy off unless the public endpoint starts blocking your IP.

## Actor input object example

```json
{
  "searchQueries": [
    "naruto"
  ],
  "type": "anime",
  "trending": false,
  "recordIds": [],
  "maxItems": 100,
  "requestDelaySecs": 0.5,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Full dataset of catalog rows and error rows.

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

Table of identifying fields for each title.

# 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 = {
    "searchQueries": [
        "naruto"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("b2b_lead_generation/kitsu-anime-manga-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 = {
    "searchQueries": ["naruto"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("b2b_lead_generation/kitsu-anime-manga-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 '{
  "searchQueries": [
    "naruto"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call b2b_lead_generation/kitsu-anime-manga-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,b2b_lead_generation/kitsu-anime-manga-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/9r2yxyqpgQ8dyaYl9/builds/ntYTudlPr8VVvevgg/openapi.json
