GuidesANIME APIS
Free anime APIs for browser JavaScript
We tested 9 anime and manga APIs from another origin on 28 October 2026. AniList, Kitsu, Shikimori, AnimeThemes, trace.moe and Anime News Network need no key and send Access-Control-Allow-Origin, so you call them straight from the page. MangaDex sends CORS headers only to its own site and tells developers to proxy; it returned 200 through the free cors.dev proxy with no signup. The official MyAnimeList API needs a client ID header that the free proxy drops, and Jikan did not answer.
Which anime APIs work from the browser
Each API got a request with Origin: https://example.com, a preflight where a browser would send one, and the same request through the free cors.dev proxy (https://proxy.cors.dev/ plus the full URL). The free proxy needs no signup and allows GET and HEAD at about 600 requests a minute per IP.
| API | Key | Free limits | Browser CORS | Through cors.dev |
|---|---|---|---|---|
| AniList | None for public data | 90 a minute, 30 while degraded | Yes, any origin, POST | Not needed; AniList blocks the proxy with 403 |
| Kitsu | None for public data | No published limit, 20 per page | Yes, any origin | 200, not needed |
| Shikimori | None for public reads | 5 a second, 90 a minute | Yes, any origin, GET | 200, not needed |
| AnimeThemes | None | 90 a minute | Yes, any origin, GraphQL POST | Not needed for GraphQL |
| trace.moe | None, sponsor key optional | 100 searches a day, 1 at a time | Yes, echoes your origin | 200, but quota then belongs to the proxy IP |
| Anime News Network | None, attribution required | 1 a second per IP | Yes, any origin, XML | 200, not needed |
| MangaDex | None, non-commercial only | About 5 a second per IP | No, only mangadex.org | 200, the proxy MangaDex asks for |
| MyAnimeList API v2 | Client ID header | Not published | No, preflight 405 | 403, the client ID header is dropped |
| Jikan v4 | None | 60 a minute, 3 a second | No answer | 522 after 19 seconds |
AniList: GraphQL with no key
AniList has one GraphQL endpoint, https://graphql.anilist.co: send a POST with a JSON body { query, variables }, with no key or token for public data. Responses carry Access-Control-Allow-Origin: * and the preflight answered 204, so call it directly.
Skip the proxy here. A GET returns 404, the free proxy refuses POST with 405, and a GET through it got 403 with AniList's own message "You have been manually blocked. Please come to the principal's office."
AniList's docs give 90 requests a minute, cut to 30 while the API is degraded, plus a burst limiter; on 28 October 2026 X-RateLimit-Limit said 30 and the 31st request inside a minute got 429. The 429 kept Access-Control-Allow-Origin: *, but JavaScript can read only X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, not Retry-After, so wait for the Unix time in X-RateLimit-Reset.
Every media entry also has idMal, the MyAnimeList ID (Frieren: AniList 154587, MAL 52991). Searching "frieren" with the code below, the top result had an averageScore of 91 and 28 episodes.
const query = `
query ($search: String) {
Page(perPage: 5) {
media(search: $search, type: ANIME) {
title { romaji english }
averageScore
episodes
siteUrl
}
}
}`;
const response = await fetch('https://graphql.anilist.co', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ query, variables: { search: 'frieren' } }),
});
// AniList exposes X-RateLimit-Reset (a Unix timestamp) to the browser, not Retry-After
if (response.status === 429) {
const resetAt = new Date(Number(response.headers.get('X-RateLimit-Reset')) * 1000);
throw new Error(`AniList rate limit hit, try again after ${resetAt.toLocaleTimeString()}`);
}
const { data, errors } = await response.json();
if (errors) throw new Error(errors[0].message);
for (const anime of data.Page.media) {
console.log(anime.title.english ?? anime.title.romaji, anime.averageScore, anime.episodes, anime.siteUrl);
}Kitsu, Shikimori and AnimeThemes
- Kitsu: JSON:API at
https://kitsu.io/api/edge,Access-Control-Allow-Origin: *, no key and no rate limit in its docs. Search withfilter[text]=and page withpage[limit](maximum 20) andpage[offset]. JSON:API nests every field underdataandattributes, so one result for "frieren" was 6,286 bytes. - Shikimori: REST at
https://shikimori.io/api(shikimori.oneredirects there);/api/animes?search=frieren&limit=1returned 512 bytes withAccess-Control-Allow-Origin: *. Its docs allow 5 requests a second and 90 a minute, want your OAuth2 application name inUser-Agentand warn that IPs can be banned without it, so keep anything beyond a personal page on a backend. - AnimeThemes: opening and ending themes. Its docs mark the JSON:API at
api.animethemes.moeas deprecated; use GraphQL athttps://graphql.animethemes.moe/(POST, CORS for any origin, 90 requests a minute).findAnimeByExternalSite(site: MAL, id: [52991])returned Frieren's 4 themes, from OP "Yuusha" to OP2 "Haru".
MangaDex: the API that asks for a proxy
https://api.mangadex.org/manga?limit=1 answered 200 (5,789 bytes) with no Access-Control-Allow-Origin for example.com, and the preflight got 403: MangaDex sends CORS headers only to https://mangadex.org. Its docs say you "MUST proxy the requests your users make to our services", and they require an honest User-Agent and no Via header.
The free cors.dev proxy fits those rules. It returned the same 5,789 bytes with 200, sends User-Agent: cors.dev/0.1 (+https://cors.dev), adds no Via header, and does not pass on your page's Referer or Origin.
That matters for covers. MangaDex answers hotlinks with a placeholder: the 256 px Frieren cover requested with a Referer or Origin from another site came back as a 59,480-byte placeholder, and through cors.dev as the real 47,314-byte cover. The proxy relays images only to requests that send an Origin, so set crossOrigin = 'anonymous', or it answers 502 unsupported_response.
const PROXY = 'https://proxy.cors.dev/';
const params = new URLSearchParams({ title: 'frieren', limit: '5', 'includes[]': 'cover_art' });
const response = await fetch(`${PROXY}https://api.mangadex.org/manga?${params}`);
if (!response.ok) throw new Error(`MangaDex answered ${response.status}`);
const { data } = await response.json();
for (const manga of data) {
const cover = manga.relationships.find((relation) => relation.type === 'cover_art');
const img = document.createElement('img');
// crossOrigin makes the browser send an Origin header, which the proxy requires for images
img.crossOrigin = 'anonymous';
img.src = `${PROXY}https://uploads.mangadex.org/covers/${manga.id}/${cover.attributes.fileName}.256.jpg`;
img.alt = manga.attributes.title.en ?? Object.values(manga.attributes.title)[0];
document.body.append(img);
}Rules to plan around:
- About 5 requests a second per IP for the whole API, then
429, then a temporary403ban if you keep going. MangaDex warns that on a proxy or shared network other users' requests count against you, and the free proxy is shared. limitabove 100 returns400, and so doesoffsetpluslimitabove 10,000.- The API is free only for projects that credit MangaDex, credit scanlation groups (and honor their removal requests) if users can read chapters, and run no ads or paid services. Donations are allowed.
cors.dev Pro ($5 a month for 500,000 requests) adds little here: its X-Cors-Cache never caches longer than the upstream allows, and MangaDex sends max-age=15.
trace.moe and Anime News Network
trace.moe finds the anime, episode and timestamp for a screenshot: GET https://api.trace.moe/search?url= plus an encoded image URL returned 200 (3,752 bytes) with the AniList ID, episode, from, to and similarity, and CORS for our origin. Without a key you get 100 searches a day per IP, 1 at a time; over either limit it answers 402, and failed searches do not count.
Call it directly. Its docs tell client apps to do so, so each visitor uses their own IP's quota; through cors.dev, /me reported a Cloudflare address, so every proxy user would share one 100-search quota.
Anime News Network's encyclopedia API returns XML: https://cdn.animenewsnetwork.com/encyclopedia/api.xml?anime=4658 sent 14,455 bytes of text/xml with Access-Control-Allow-Origin: *, ready for DOMParser. It allows 1 request a second per IP (extra requests wait), and you must credit Anime News Network and link to the encyclopedia entry wherever you show its data.
MyAnimeList and Jikan
The official MyAnimeList API v2 needs an X-MAL-CLIENT-ID header, sends no CORS headers and answered the preflight with 405. The free proxy drops that header (listed in X-Cors-Dropped-Headers), so MAL answers 403. The MyAnimeList API guide covers the backend Worker and cors.dev Pro routes.
Jikan (api.jikan.moe/v4), the unofficial MyAnimeList API, needs no key and documents 60 requests a minute and 3 a second. On 28 October 2026 a direct request timed out after 15 seconds and the proxy returned 522 after 19 seconds. Until it answers again, get MyAnimeList IDs from AniList's idMal or AnimeThemes' findAnimeByExternalSite.
Good questions.
What is the best free anime API for a JavaScript app?
AniList for most apps: GraphQL, no key, CORS for any origin, and MyAnimeList IDs in idMal. Kitsu and Shikimori suit REST, AnimeThemes covers theme songs, and MangaDex covers manga on non-commercial sites.
Does AniList need an API key?
No. Public queries to https://graphql.anilist.co need no key or token; send a POST with { query, variables } straight from the page. Expect 30 requests a minute while the API is degraded and 90 otherwise.
Why does MangaDex block fetch requests from my site?
MangaDex sends CORS headers only to https://mangadex.org, and its docs tell you to proxy your users' requests. Through https://proxy.cors.dev/ the same request returned 200, and covers came back as the real files instead of the hotlink placeholder.
Is Jikan down?
It did not answer on 28 October 2026: a direct request timed out after 15 seconds and cors.dev got 522 after 19 seconds. Until it is back, take MyAnimeList IDs from AniList's idMal.
Can I use the MangaDex API on a site with ads?
No. MangaDex's usage policy allows the API only for projects with no ads and no paid services; donations are fine. You must also credit MangaDex, and scanlation groups if users can read chapters.
How do I find which anime a screenshot is from?
Send GET https://api.trace.moe/search?url= with the encoded image URL, directly from the browser. Each visitor's IP gets 100 free searches a day, and each match includes the episode and timestamps.