miribyou is a lightweight, database-free MyAnimeList (MAL) scraper that
provides structure and data parity with the Jikan v4 API.
miribyou requires no database setup, and the API itself is platform-agnostic:
the entire route surface lives in a single portable Hono app
(src/app.ts), with thin per-platform adapters on top. It runs unmodified on
Cloudflare Workers, Vercel Functions, or any Docker/Node host—pick whichever fits
your rate limits, budget, or CPU-time needs. It achieves high-fidelity JSON output
by parsing MAL's HTML directly, optionally enhanced by the official MAL API.
Important
This project aims for parity with Jikan V4 data structures and versioning.
All endpoints are prefixed with /v4.
Warning
Because miribyou does not rely on a persistent database, some advanced
search or filtering queries may return stub/partial data. Providing a
MAL_CLIENT_ID helps resolve many of these limitations.
# Clone and install
git clone https://github.com/nattadasu/miribyou.git
cd miribyou
npm install # or: bun install
# Run with any of these (all work out of the box):
bun run src/server.bun.ts # Bun
deno run --allow-net --allow-env src/server.deno.ts # Deno 2.9.0+
npx tsx src/server.ts # Node 24+ (via tsx)The server starts on http://0.0.0.0:7860 by default. Set PORT to change it.
src/app.ts — the actual API: every route, parser call, and the Hono instance itself
src/index.ts — Cloudflare Workers adapter
src/server.ts — Node/Docker adapter
src/server.deno.ts — Deno adapter
src/server.bun.ts — Bun adapter
api/index.ts — Vercel adapter
src/app.ts has zero platform-specific code. Each adapter is just a few lines
that hand it that platform's (request, env, ctx) triple.
| Target | Entrypoint | Best for |
|---|---|---|
| Cloudflare Workers | src/index.ts |
Free global edge, generous free tier |
| Vercel | api/index.ts |
Zero-config Git deploys |
| Docker/Node | src/server.ts |
No per-request CPU-time cap — best for ?hover=1/heavy concurrent-fetch traffic; Docker is untested |
| Bun | src/server.bun.ts |
Fast startup, zero config |
| Deno | src/server.deno.ts |
Native TS, secure defaults |
npm install
npx wrangler login
npm run deployNote
Workers' free tier enforces a per-request CPU-time budget. Endpoints that
fan out into several concurrent MAL fetches (e.g. ?hover=1) can hit that
ceiling under load—use the Docker target for unlimited CPU time.
Link your GitHub repo to Vercel, or click the Deploy with Vercel button
above. The function runs on the Node.js runtime. Set MAL_CLIENT_ID under
Project Settings → Environment Variables if desired.
docker build -t miribyou .
docker run -p 7860:7860 -e MAL_CLIENT_ID=your_client_id miribyouFor a Hugging Face Space: create a Docker-SDK Space, push this repo, and
set MAL_CLIENT_ID as a Space secret. The app_port should be 7860.
bun install
bun run src/server.bun.tsWarning
Requires v2.9.0
deno install # or: deno cache src/server.deno.ts
deno run --allow-net --allow-env src/server.deno.tsnpm install # or: bun install
npm run dev # hot-reloading via Wrangler (Cloudflare Workers simulator)
npm test # Vitest test suiteYou can also run the server directly with any runtime during development — see Quick Start.
Set MAL_CLIENT_ID as an environment variable or pass the
X-MAL-CLIENT-ID header per-request. Get a Client ID at
MyAnimeList API Config by creating a new
Web client. If redirect URL is required, set http://localhost:8787
miribyou identifies itself with the X-Powered-By: miribyou (Jikan-like)
response header.
const res = await fetch("https://api.example.com/v4/anime/1");
const isMiribyou = res.headers.get("X-Powered-By") === "miribyou (Jikan-like)";Successful GET responses (2xx) include cache headers for 1 day:
Cache-Control: public, max-age=86400, s-maxage=86400CDN-Cache-Control: public, max-age=86400, s-maxage=86400Vercel-CDN-Cache-Control: public, max-age=86400, s-maxage=86400
Caching is bypassed on / and /v4/ base metadata endpoints, and on any
non-GET or unsuccessful requests.
All endpoints are GET requests.
GET /v4/— API metadata and heartbeat
GET /v4/anime?q=query— Search animeGET /v4/anime/:id— Basic detailsGET /v4/anime/:id/full— Full metadata (relations, themes, etc.)GET /v4/anime/:id/characters— CharactersGET /v4/anime/:id/staff— Production staffGET /v4/anime/:id/episodes— Episodes (?page=n)GET /v4/anime/:id/episodes/:episodeId— Single episodeGET /v4/anime/:id/news— News (?page=n)GET /v4/anime/:id/forum— Forum topicsGET /v4/anime/:id/videos— Promotional videos and streaming linksGET /v4/anime/:id/videos/episodes— Episode videos (?page=n)GET /v4/anime/:id/pictures— ImagesGET /v4/anime/:id/statistics— Score distribution and watch statsGET /v4/anime/:id/moreinfo— Additional infoGET /v4/anime/:id/recommendations— User recommendationsGET /v4/anime/:id/userupdates— Latest list updatesGET /v4/anime/:id/reviews— Reviews (?page=n)GET /v4/anime/:id/relations— Related entriesGET /v4/anime/:id/themes— Opening/ending themesGET /v4/anime/:id/external— External linksGET /v4/anime/:id/streaming— Streaming platform links
GET /v4/manga?q=query— Search mangaGET /v4/manga/:id— Basic detailsGET /v4/manga/:id/full— Full metadataGET /v4/manga/:id/characters— CharactersGET /v4/manga/:id/news— News (?page=n)GET /v4/manga/:id/forum— Forum topicsGET /v4/manga/:id/pictures— ImagesGET /v4/manga/:id/statistics— Reading statsGET /v4/manga/:id/moreinfo— Additional infoGET /v4/manga/:id/recommendations— RecommendationsGET /v4/manga/:id/userupdates— List updatesGET /v4/manga/:id/reviews— Reviews (?page=n)GET /v4/manga/:id/relations— Related entriesGET /v4/manga/:id/external— External links
GET /v4/characters/:id— Basic info (name, images, about, favorites)GET /v4/characters/:id/full— Full data with anime/manga/voice actor appearancesGET /v4/characters/:id/anime— Anime appearances with rolesGET /v4/characters/:id/manga— Manga appearances with rolesGET /v4/characters/:id/voices— Voice actorsGET /v4/characters/:id/pictures— Image gallery
GET /v4/seasons— List of archived years/seasonsGET /v4/seasons/now— Current seasonGET /v4/seasons/upcoming— Upcoming seasonGET /v4/seasons/:year/:season— Specific archive
GET /v4/users?q=query— Search usersGET /v4/users/recentlyonline— Recently onlineGET /v4/users/userbyid/:id— Get username by MAL IDGET /v4/users/:username— ProfileGET /v4/users/:username/full— Full profileGET /v4/users/:username/statistics— Anime/manga list statsGET /v4/users/:username/favorites— FavoritesGET /v4/users/:username/userupdates— Latest updatesGET /v4/users/:username/about— About section (raw HTML)GET /v4/users/:username/history— History (?type=anime|manga)GET /v4/users/:username/friends— FriendsGET /v4/users/:username/animelist— Anime listGET /v4/users/:username/mangalist— Manga listGET /v4/users/:username/recommendations— RecommendationsGET /v4/users/:username/reviews— ReviewsGET /v4/users/:username/clubs— ClubsGET /v4/users/:username/external— External accounts
| Parameter | Alias | Type | Default | Description |
|---|---|---|---|---|
page |
p |
integer |
1 |
Pagination index number |
Accessible only when endpoint has a struct of { pagination, data } where data
is an array of entries and pagination contains last_visible_page and
has_next_page.
Do aware that using last_visible_page may unreliable on some endpoints as MAL
does not expose it properly
Note
All paginated endpoints accept both ?page=n and ?p=n.
| Parameter | Type / Format | Description |
|---|---|---|
q |
string |
Search query |
page |
integer |
Page number |
limit |
integer |
Results per page (default: 25) |
type |
TV, OVA, Movie, Special, ONA, Music |
Media type filter |
score, min_score, max_score |
number |
Score filter |
status |
airing, complete, upcoming |
Airing status filter |
rating |
g, pg, pg13, r17, r, rx |
Age rating filter |
sfw |
boolean |
Filter out NSFW/adult entries |
genres, genres_exclude |
string |
Comma-separated genre IDs |
order_by |
string |
Sort field (mal_id, title, start_date, score, etc.) |
sort |
desc, asc |
Sort direction |
letter |
string |
First letter filter |
producers |
string |
Comma-separated producer IDs |
start_date, end_date |
YYYY-MM-DD |
Date range |
hover=1 |
flag |
Opt-in extended metadata (slower; fetches popup fields) |
| Parameter | Type / Format | Description |
|---|---|---|
q |
string |
Search query |
page |
integer |
Page number |
limit |
integer |
Results per page (default: 25) |
type |
manga, novel, lightnovel, oneshot, doujin, manhwa, manhua |
Media type filter |
score, min_score, max_score |
number |
Score filter |
status |
publishing, complete, hiatus, discontinued, upcoming |
Publication status filter |
sfw |
boolean |
Filter out NSFW/adult entries |
genres, genres_exclude |
string |
Comma-separated genre IDs |
order_by |
string |
Sort field (mal_id, title, chapters, score, etc.) |
sort |
desc, asc |
Sort direction |
letter |
string |
First letter filter |
magazines |
string |
Comma-separated magazine IDs |
start_date, end_date |
YYYY-MM-DD |
Publication date range |
hover=1 |
flag |
Opt-in extended metadata |
| Parameter | Type / Format | Description |
|---|---|---|
q |
string |
Search query (required) |
page |
integer |
Page number |
limit |
integer |
Results per page (default: 25) |
gender |
any, male, female, nonbinary |
Gender filter |
location |
string |
Location filter |
minAge, maxAge |
integer |
Age range filter |
| Parameter | Type / Format | Description |
|---|---|---|
page |
integer |
Page number |
limit |
integer |
Results per page (default: 25) |
filter |
tv, movie, ova, special, ona, music |
Media type filter |
sfw |
boolean |
Exclude Rx/Hentai |
hover=1 |
flag |
Opt-in extended metadata |
Warning
Use ?hover=1 sparingly — it fires concurrent background requests for each
entry on the page, increasing response times. Only supported on the HTML
scraper fallback path.
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer |
1 |
Page number |
preliminary |
boolean |
true |
Include preliminary reviews (during ongoing airing/publishing) |
spoilers |
boolean |
true |
Include reviews with spoilers |
MIT. See LICENSE.