An unofficial API specification for MyAnimeList
An unofficial specification for MyAnimeList.net's long undocumented APIs. GPLv3 Licensed.
For starters, I've only been a MyAnimeList user for a short period of time. Nevertheless, as far as I know, MyAnimeList was and still is the largest anime information database website, which also happens to be infamous to the developers for its unstable APIs.
This document intends to create an up-to-date specification for the private (open-beta) APIs that MyAnimeList is using in its official mobile apps. The goal is to encourage the developments of third-party and (particularly) open source applications.
As mentioned, the specifications here (mostly) came from the analysis of MyAnimeList's official Android app and some popular third-party applications. Note because this document uses MAL's private (or at least unpublished) APIs, everything is subject to change.
This document only discovers the anime-related APIs. But feel free to create a pull request/issue if you have something related that you want to share or change.
API Endpoint: https://api.myanimelist.net/v2
Client Identifier (from MAL's official Android app): 6114d00ca681b7701d1e15fe11a4987e
Example Request
GET /v2/anime/search?status=not_yet_aired&limit=1&offset=0&fields=alternative_titles HTTP/1.1
Host: api.myanimelist.net
Accept: application/json
User-Agent: NineAnimator/2 CFNetwork/976 Darwin/18.2.0
Authorization: Bearer <OAuth2 Token>
X-MAL-Client-ID: 6114d00ca681b7701d1e15fe11a4987e
Note: Always include the
X-MAL-Client-ID
header. Currently the only known client id is that of the MAL's official Android app.
If the request is intended for mutations (e.g. modify user library entries),
the request body is url-form encoded with content type: application/x-www-form-urlencoded
.
The responses are formatted in json with content type
application/json; charset=UTF-8
.
If the request succeeded, the server returns 200
with a data
object at the
root of its response JSON object.
Example Response
HTTP/1.1 200 OK
{
"data": [
{
"node": {
"id": 34134,
"title": "One Punch Man Season 2",
"main_picture": {
"medium": "https:\/\/myanimelist.cdn-dena.com\/images\/anime\/1797\/93459.jpg",
"large": "https:\/\/myanimelist.cdn-dena.com\/images\/anime\/1797\/93459l.jpg"
},
"alternative_titles": {
"synonyms": [ "One Punch-Man 2", "One-Punch Man 2","OPM 2" ],
"en": "",
"ja": "\u30ef\u30f3\u30d1\u30f3\u30de\u30f3 2"
}
}
}
],
"paging": {
"next": "https:\/\/api.myanimelist.net\/v2\/anime\/search?offset=2&status=not_yet_aired&limit=2&fields=alternative_titles"
}
}
If the request failed, the server respond with an HTTP error status and returns an error message.
Example Response
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=UTF-8
{ "message": "invalid q", "error": "bad_request" }
OAuth2 is used in MAL's authentication scheme. Two tokens will be returned
upon a successful authentication: the access_token
and the refresh_token
.
Once authenticated, all of your requests should include the header
Authentication
with value Bearer <access_token>
.
Send a url-form encoded POST
request to https://api.myanimelist.net/v2/auth/token
with the following parameters:
Parameter | Value |
---|---|
client_id |
String: 6114d00ca681b7701d1e15fe11a4987e |
grant_type |
String: password |
password |
String: The account's password |
username |
String: The account's username |
Example Request
POST /v2/auth/token HTTP/1.1
Host: api.myanimelist.net
Accept: application/json
User-Agent: NineAnimator/2 CFNetwork/976 Darwin/18.2.0
X-MAL-Client-ID: 6114d00ca681b7701d1e15fe11a4987e
Content-Type: application/x-www-form-urlencoded
Content-Length: 112
client_id=6114d00ca681b7701d1e15fe11a4987e&grant_type=password&password=xxxxxx-yyyyyy-zzzzzz&username=abcdefghij
refresh_token
Send a url-form encoded POST
request to https://myanimelist.net/v1/oauth2/token
(note this url is different from the one used in the Password Grant).
Parameter | Value |
---|---|
client_id |
String: 6114d00ca681b7701d1e15fe11a4987e |
grant_type |
String: refresh_token |
refresh_token |
String: The refresh token previously received |
Example Request
POST /v1/auth/token HTTP/1.1
Host: myanimelist.net
Accept: application/json
User-Agent: NineAnimator/2 CFNetwork/976 Darwin/18.2.0
X-MAL-Client-ID: 6114d00ca681b7701d1e15fe11a4987e
Content-Type: application/x-www-form-urlencoded
Content-Length: 88
client_id=6114d00ca681b7701d1e15fe11a4987e&grant_type=refresh_token&refresh_token=xxxxxx
200 OK
and a JSON
object with the following entries:Entry | Value |
---|---|
token_type |
String: Bearer |
expires_in |
Integer: The lifespan of the responded access token in seconds, after which the client needs to be reauthenticated. |
access_token |
String: The access token that should be included in further requests from this client. |
refresh_token |
String: The refresh token that can be used to re-authenticate the client with Refresh Token Grant |
You should persist the refresh_token
in a secure location. When the access_token
expires after expires_in
seconds, use the refresh_token
to re-authenticate the
session. See Refresh Token Grant.
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "xxxx",
"refresh_token": "xxxx"
}
Further requests should be made with the Authorization
header. See Making Requests.
Entry | Value |
---|---|
error |
String: The type of the error |
message |
String: A human-readable description of the error. |
(Optional) hint |
String: An optional message about how the error occurred. |
Example Response
HTTP/2 401
Content-Type: application/json; charset=UTF-8
{
"error": "invalid_request",
"message": "The refresh token is invalid.",
"hint": "Cannot decrypt the refresh token"
}
Resource requests are made to the endpoint https://api.myanimelist.net/v2
.
X-MAL-Client-ID
header, or you will get an unauthorized
error. See Making Requests
https://api.myanimelist.net/v0.21
still works.https://api.myanimelist.net/v0.8
. But
when you make a mutational request to this endpoint, the server will responds
an outdated app error.Set the following GET parameters in your request url to limit the number of resources included in the response:
Parameter | Value |
---|---|
limit |
The maximum number of elements to be contained in the data section. |
offset |
The page number that the client is requesting. |
Example Request URL with Paging
https://api.myanimelist.net/v2/anime?q=An+Anime+Title&limit=5&offset=0
When the response is paged, the JSON object returned also includes a paging
section. The next
entry in the paging
section includes the full URL to the
next page.
Exampled Response with Paging
{
"data": [ ... ],
"paging": {
"next": "https:\/\/api.myanimelist.net\/v2\/anime?offset=5&q=An+Anime+Title&limit=5"
}
}
When you make a request to a specific resource, you can set the fields
parameter in your URL query to limit the fields responded by the server.
fields
parameter whenever you can. This decreases the load
time and (perhaps) decreases the load on MAL's server as well.fields
parameter is a comma seperated list
corresponding to the JSON keys that will be returned in the response.<Subsection Name>{<Subsection Entry 1>, <Subsection Entry 2>, <Subsection Entry 3>...}
.Example Request URL with Fields parameter
https://api.myanimelist.net/v2/anime?q=An+Anime+Title&fields=alternative_titles,media_type,my_list_status{start_date,finish_date}
A list of known request paths and response objects.
https://api.myanimelist.net/v2
/users/<user id>
GET
This operation doesn't require any parameters. Note @me
can be used in place of <user id>
. See Referring the Current User.
An UserObject
.
Example Request
GET https://api.myanimelist.net/v2/users/@me HTTP/2.0
authorization: Bearer <bearer token>
Example Response
HTTP/2.0 200
content-type: application/json; charset=UTF-8
{"id":1234567,"name":"username","location":"some location","joined_at":"2010-01-01T01:11:11+00:00"}
/anime/<anime id>
GET
This operation supports the use of the fields
parameter.
An AnimeObject
.
/anime
GET
, response supports pagingParameter | Value |
---|---|
q |
String: Keywords to be used as search parameters |
Object
data
: Array<AnimeObject>
- A list of AnimeObject
. The results from the search./users/<User Identifier>/animelist
GET
, response supports pagingParameter | Value |
---|---|
sort |
SortingMethodEnum: The method of sorting the responsing entries. |
status |
ListStatusEnum: Filter the status of the entries. |
Object
data
: Array<AnimeObject>
- A list of AnimeObject
./anime/<Anime Identifier>/my_list_status
PATCH
or PUT
The parameters are url-form encoded in the body of the request. The parameter keys resembles those found in MyListStatusObject
.
Parameter | Value |
---|---|
num_watched_episodes |
An integer denoting the number of episodes watched. Note this is different from the key in MyListStatusObject (#1). |
status |
ListStatusEnum |
score |
An integer representing the user's rating. Value ranging from 1 to 10. Set this value to 0 to remove the user's rating. |
start_date |
A year-month-day string that indicates when the user started watching the entry (eg. 2020-1-1 ). |
finish_date |
A year-month-day string that indicates when the user finished watching the entry (eg. 2020-1-1 ). |
MyListStatusObject
- The updated status objectExample Request
PATCH https://api.myanimelist.net/v2/anime/34881/my_list_status HTTP/2.0
authorization: Bearer <bearer token>
content-type: application/x-www-form-urlencoded
finish_date=2020-01-1&start_date=2020-02-01&num_watched_episodes=2
Example Response
HTTP/2.0 200
content-type: application/json; charset=UTF-8
{"status":"on_hold","score":0,"num_episodes_watched":2,"is_rewatching":false,"updated_at":"2020-01-1T20:50:00+00:00","start_date":"2020-01-01","finish_date":"2020-02-1","priority":0,"num_times_rewatched":0,"rewatch_value":0,"tags":[],"comments":""}
/anime/<Anime Identifier>/my_list_status
DELETE
No parameters needed for this operation.
An empty array []
for a successful removal.
Example Request
DELETE https://api.myanimelist.net/v2/anime/39590/my_list_status HTTP/2.0
authorization: Bearer <bearer token>
Example Response
HTTP/2.0 200
content-type: application/json; charset=UTF-8
[]
You can reference to the currently authenticated user with the
@me
placeholder in the request URL.
Example Request URL
https://api.myanimelist.net/v2/users/@me/animelist
AnimeObject
An AnimeObject
represents an anime in MAL's database.
AnimeObject
: Object
node
: Object
alternative_titles
: AlternativeTitlesObject
average_episode_duration
: Int - The average duration (in seconds) of the episodes.broadcast
: BroadcastObject
created_at
: Date
end_date
: CalendarDate
- The date at which the anime ended.genres
: Array
<GenreObject
> - Genres of the anime.id
: Int
- The identifier of this media on MyAnimeList.main_picture
: PictureObject
- The poster artwork of the anime.mean
: Double
- The mean score of this media on MyAnimeList.media_type
: String
- The type of this media (tv
, ova
, movie
, special
, ona
, music
, unknown
).nsfw
: String
- The NSFW state for this media (white
, gray
, black
).num_episodes
: Int
- The number of episodes in this anime.num_favorites
: Int
- The number of users that added this media to their favorites.num_list_users
: Int
- The number of uses that added this media to their lists.num_scoring_users
: Int
- (?) The number of users that voted for the scores.popularity
: Int
- The popularity rankings of this anime.rank
: Int
- The rankings of this anime.start_date
: CalendarDate
- The date at which the anime started.start_season
: SeasonObject
- The season at which the anime started broadcasting.status
: String
- An enumeration representing the broadcasting status of the anime (finished_airing
, currently_airing
, not_yet_aired
).synopsis
: String
- The synopsis of the anime.source
: String
- The original work that inspired this anime (original
, manga
, 4_koma_manga
, web_manga
, digital_manga
, novel
, light_novel
, visual_novel
, game
, card_game
, book
, picture_book
, radio
, music
, other
).studio
: AnimeStudioObject
title
: String
- The canonical (?) title of the anime.updated_at
: Date
- The last time that the information is updated on MyAnimeList.my_list_status
: MyListStatusObject
background
: String
- Background story of the animerelated_anime
: Array<AnimeObject>
- A list of anime related to this animerating
: String
- The rating of this anime (g
All Ages, pg
Children, pg_13
Teens 13 and Older, r
17+ (violence & profanity), r+
Profanity & Mild Nudity, rx
Hentai).AlternativeTitlesObject
The set of titles and synonyms of the anime.
AlternativeTitlesObject
: Object
en
: String
- The English title of the mediaja
: String
- The original (native) name of the mediasynonyms
: Array<String>
- A list of synonyms of the mediaAnimeStudioObject
The studio of the anime.
AnimeStudioObject
: Object
id
: Integer
- The id of the studioname
: String
- The name of the studioBroadcastObject
The broadcasting schedule of the anime.
BroadcastObject
: Object
day_of_the_week
: String
- A lower-cased string of the day that the media is released in a week. E.g. thursday
start_time
: String
- The time of the broadcast. E.g. 19:30
CalendarDate
A simple date formatted as yyyy-mm-dd
(e.g. 2007-02-08
).
CalendarDate
: String
Date
A specific time.
Date
: String
- A ISO 8601
formatted time string.GenreObject
The genre of the anime.
GenreObject
: Object
id
: Integer
- The id of the genrename
: String
- The name of the genre (Action
, Adventure
, Cars
, Comedy
, Dementia
, Demons
, Drama
, Ecchi
, Fantasy
, Game
, Harem
, Hentai
, Historical
, Horror
, Josei
, Kids
, Magic
, Martial Arts
, Mecha
, Military
, Music
, Mystery
, Parody
, Police
, Psychological
, Romance
, Samurai
, School
, Sci-Fi
, Seinen
, Shoujo
, Shoujo Ai
, Shounen
, Shounen Ai
, Slice of Life
, Space
, Sports
, Super Power
, Supernatural
, Thriller
, Vampire
, Yaoi
, Yuri
)PictureObject
A set of pictures.
PictureObject
: Object
large
: String
- An absulute URL to the high(er) resolution picturemedium
: String
- An absulute URL to the medium resolution pictureSortingMethodEnum
The method of sorting the entries in the response lists.
SortingMethodEnum
: String
- One of anime_title
, list_score
, list_updated_at
, anime_start_date
SeasonObject
Representing a season in a year.
SeasonObject
: Object
season
: String
- The season in a year (E.g. fall
).year
: Int
- The four digits integer representation of a year (E.g. 2002
).ListStatusEnum
The list status of the user.
ListStatusEnum
: String
- One of watching
, completed
, on_hold
, dropped
, plan_to_watch
MyListStatusObject
The library entry.
MyListStatusObject
: Object
comments
: String
is_rewatching
: Bool
num_episodes_watched
: Int
num_times_rewatched
: Int
priority
: Int
rewatch_value
: Int
score
: Double
status
: ListStatusEnum
tags
: ?updated_at
: Date
UserObject
UserObject
: Object
id
: Int
An integer id of the user.name
: String
location
: String
joined_at
: Date