User profiles
Retrieve a public username, profile URL and anime-list URL.
MyAnimeList Public Data API
Access public MyAnimeList user profiles, anime lists and statistics through a clean and lightweight JSON API.
https://api.elvarora.com/v2/users/:username/1{
"data": {
"user": {
"username": "example"
},
"statistics": {
"anime": {
"completed": 120,
"episodes_watched": 1432,
"mean_score": 8.42
}
}
}
}Structured data.
Ready for your next integration.
01 / API OVERVIEW
Elvarora API provides structured JSON access to public MyAnimeList user data.
The API is designed to make public MAL profile and anime-list data easier to consume in web applications, dashboards, bots and other developer tools.
Elvarora API is an independent service and is not affiliated with or endorsed by MyAnimeList.
GET /v2/users/:username/1One upstream page of up to 300 anime, public-profile statistics and ETag revalidation. No full-list download; scored_entries is null.
Retrieve a public username, profile URL and anime-list URL.
Watching, completed, plan-to-watch, episode counts and mean scores.
Access public entries with titles, scores, progress, genres and update timestamps.
Consume large lists one page at a time with a V2 page number in the URL.
Normalized fields that fit into web apps, dashboards, bots and developer tools.
Retrieve publicly available information without modifying a MyAnimeList account.
| Capability | V1 · Legacy | V2 · Recommended |
|---|---|---|
| Public user data | Yes | Yes |
| Anime statistics | Yes | Yes |
| Anime list | Yes | Yes |
| JSON response | Yes | Yes |
| ETag conditional requests | Yes | Yes |
| 304 Not Modified | Yes | Yes |
| Authentication required | No | No |
| Pagination | — | Yes |
| Up to 300 entries per page | — | Yes |
| Page number in the URL | — | Yes |
| Pagination metadata | — | Yes |
V2 is recommended for new integrations and fetches only the requested 300-entry page. V1 is retained as a legacy full-response endpoint. V2 statistics come from the MAL profile; scored_entries is null and episode totals may differ from V1.
02 / DEVELOPER CONSOLE
Start with V2, the recommended API for new integrations. It loads one responsive 300-entry page at a time. V1 is the legacy full-response endpoint and can be slow for large lists.
https://api.elvarora.com/v2/users//1Your response will appear here.
Send a request to inspect live JSON.https://api.elvarora.com/v1/users/Legacy endpoint. Returns the complete supported list in a single response and may be slow for large accounts.
Your response will appear here.
Send a request to inspect live JSON.V2 · Recommended Use V2 for new integrations and large lists. It keeps requests and browser rendering responsive.
V1 · Legacy Use V1 only when an existing integration requires the complete supported list in one response.
03 / DOCUMENTATION
Returns public user information, anime statistics and supported list data.
/v2/users/:username/:page RECOMMENDEDFetches only the requested page of up to 300 anime without loading the complete list. Includes public-profile statistics and next/previous links. Recommended for new integrations and large lists.
https://api.elvarora.com/v2/users/example/1/v1/users/:username LEGACYLegacy full response with the complete supported anime list. Use only when an existing integration requires one large response.
https://api.elvarora.com/v1/users/example| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
username | string | Yes | — | 2–32 letters, numbers, underscores or hyphens. |
limit | integer | No | 300 | Fixed V2 page size. Do not add a limit query parameter. |
page | integer | Yes | — | V2 path segment: /v2/users/aa/2 opens page 2. Range: 1–10000. |
The new page route accepts no query parameters. Pages beyond the list return an empty list. The legacy /v2/users/:username?limit=50&page=1 route remains compatible, but still loads the full list and retains the old large-list limits. Its limit defaults to 50 (range 1–100). V1 returns the full list and does not accept a page segment; use V2 for pagination.
200 OK304 Not Modified400 Bad Request404 Not Found422 Unprocessable Content429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service UnavailableLimits use separate 60-second fixed windows: cache_hit allows 120 cached requests per IP; cache_miss allows 30 uncached or negative-result requests per IP; username allows 120 uncached requests for one username across all IPs; global allows 3000 user-route requests across the service; distinct_usernames allows 20 distinct usernames per IP. A 429 reports the first exhausted budget in that order. Successful requests report the applicable IP budget.
Validation errors, unknown routes, health checks and OPTIONS requests return before these budgets are consumed, so they have no request-budget headers. A user-not-found response does consume the miss budget, even when served from the short internal negative cache.
04 / INTEGRATION
Use the tools you already know. Replace example with a public MAL username.
const response = await fetch(
"https://api.elvarora.com/v2/users/example/1"
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const { data, pagination } = await response.json();
console.log(data.anime_list);
console.log(pagination.next);05 / RESPONSE STRUCTURE
The shape of a successful response, directly from the API contract.
dataobject Required · Both versionsRoot payload containing public user information, statistics and anime entries.
data.userobject Required · Both versionsusername, profile_url and anime_list_url.
data.statistics.animeobject Required · Both versionsdays_watched, mean_score, watching, completed, on_hold, dropped, plan_to_watch, total_entries, rewatched, episodes_watched and scored_entries. V1 derives list totals from all entries. New V2 pages use MAL public-profile totals (including its episode/rewatch accounting); scored_entries is null because the profile does not expose it. Other unavailable profile fields are null. No page-only count is presented as a full-list total.
data.anime_listarray<object> Required · Both versionsNormalized entries: mal_id, titles, URLs, media_type, list_status, score, episode progress, dates, genres, demographics and updated_at. The complete supported list in V1; the requested page in V2.
metaobject Required · Both versionssource, fetched_at (ISO timestamp) and cache_seconds. Read cache duration from the actual response.
paginationobject Required · V2 onlyPage navigation and totals for data.anime_list. Not present in V1.
pagination V2 field reference| Field | Type | Description |
|---|---|---|
page | integer | Current page. |
limit | integer | Maximum number of entries on this page. |
total_items | integer | Total number of available list entries. |
total_pages | integer | Number of available pages; at least 1, even for an empty list. |
has_previous | boolean | Whether a previous page exists. |
has_next | boolean | Whether another page exists. |
previous | string | null | Previous-page API path, or null. |
next | string | null | Next-page API path, or null. |
{
"pagination": {
"page": 1,
"limit": 300,
"total_items": 950,
"total_pages": 4,
"has_previous": false,
"has_next": true,
"previous": null,
"next": "/v2/users/example/2"
}
}Individual list fields such as titles, dates and update timestamps may be null when unavailable. Documentation examples are illustrative; the playground displays actual API responses.
06 / UNDER THE HOOD
From a public profile to a response your application can use.
Cached requests return directly from the API. Recommended V2 requests fetch only the requested list page; V1 and legacy V2 fetch the complete list.
Small surface area. Familiar web standards.
Successful data and API error responses use JSON.
Only publicly available MyAnimeList information is processed.
Call the public user endpoints without an API key.
Public GET requests support cross-origin access with CORS.
The API does not modify MyAnimeList accounts.
Both API domains share a 600-second server cache for versioned user data. Check meta.cache_seconds, X-Cache and Age on your response.
api.elvarora.com and api.akaydesu.com use the same cache for the same username and requested data or page. A fetch through either domain makes that snapshot available through both for 600 seconds. X-Cache-Scope: shared-user identifies the shared handler; X-Cache: HIT or MISS identifies whether successful data came from cache.
Username matching ignores letter case. For example, xinil and XINIL share cached source data, while response fields and links preserve the requested spelling. Their ETags can therefore differ.
User-not-found results have a 20-second internal negative cache and still count against the miss budget. Generic upstream failures (502) are not cached. HTTP error responses use no-store.
Retrieve data, inspect headers, or check cross-origin request options.
Cache-Control: public, no-cache asks HTTP clients to revalidate before reuse; it does not disable the shared 600-second server cache. Age describes the age of cached data.
V1 and V2 support ETag-based conditional requests, allowing clients to avoid downloading unchanged responses. Save the response ETag and send it as If-None-Match; a match returns 304 Not Modified without a body.
Browser, server and command-line clients can use the returned ETag unchanged, including its W/ prefix. CORS exposes ETag, Retry-After and request-budget headers and permits If-None-Match.
curl -i \
-H 'If-None-Match: "<saved-etag>"' \
"https://api.elvarora.com/v2/users/example/1"07 / RELIABILITY
Current availability and 30 days of monitoring history.
Last checked: unavailable
Last checked: unavailable
Source: Elvarora monitoring. Refreshes about every 60 seconds while this tab is visible; monitor checks run every 5 minutes. API health is checked at /health.