Forum Settings
Forums

[Nov 2021] Public information can now be accessed without authentication

New
Reply Disabled for Non-Club Members
Pages (2) « 1 [2]
Feb 23, 2023 9:54 AM
四十二

Offline
Mar 2016
467
wMw_ said:
Am I allowed to hardcode client-id? So there's no action needed by users for application to work properly.

Yes, you can. The OAuth 2.0 RFC defines two client types:
• Confidential:
    Clients capable of maintaining the confidentiality of their
    credentials (e.g., client implemented on a secure server with
    restricted access to the client credentials), or capable of secure
    client authentication using other means.

• Public:
    Clients incapable of maintaining the confidentiality of their
    credentials (e.g., clients executing on the device used by the
    resource owner, such as an installed native application or a web
    browser-based application), and incapable of secure client
    authentication via any other means.

Your application falls into the second category. MAL provides public clients with only a Client ID as they're unable to properly store any kind of credentials.
The Client ID is considered public information.

To register your application as a public client, you must set your App Type to "other", "Android", or "iOS". The "web" type is the only one reserved for confidential clients.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Feb 23, 2023 10:30 AM

Offline
Jun 2009
58
Thank you for confirmation! Arigatou
Mar 24, 2023 11:32 PM
Offline
Feb 2015
1
When trying to return lists of anime, I've found that some anime are 'ghosts'. What I mean is, if you run the request: https://api.myanimelist.net/v2/anime?q=Lycoris_Recoil

Trying to get the result:  https://myanimelist.net/anime/50709/Lycoris_Recoil

but for some reason, in the response list, that specific anime doesn't exist, however, it returns this:  https://myanimelist.net/anime/54440/Lycoris_Recoil_Shinsaku_Animation
but this is not what I need to return.

Since Lycoris Recoil is in my currently watching, and I want to return a response of all 14 of the shows in my currently watching, no matter what I do,  I only get 13 items back in the list. Has anyone else encountered this issue or have an idea for a fix?
BattlemuffinsMar 24, 2023 11:35 PM
Mar 25, 2023 7:19 AM
四十二

Offline
Mar 2016
467
@Battlemuffins, your problem is that the query is missing the nsfw=true parameter, briefly explained at the very top of the documentation.

The following query will return both entries:
GET https://api.myanimelist.net/v2/anime?q=Lycoris_Recoil&nsfw=true

...
"data": [
        {
            "node": {
                "id": 54440,
                "title": "Lycoris Recoil (Shinsaku Animation)",
                "main_picture": {...}
            }
        },
        {
            "node": {
                "id": 50709,
                "title": "Lycoris Recoil",
                "main_picture": {...}
            }
        },
...


If you replace the underscore with a white space, you'll get the main anime as the first result:
GET https://api.myanimelist.net/v2/anime?q=Lycoris%20Recoil&nsfw=true

...
"data": [
        {
            "node": {
                "id": 50709,
                "title": "Lycoris Recoil",
                "main_picture": {...}
            }
        },
        {
            "node": {
                "id": 54440,
                "title": "Lycoris Recoil (Shinsaku Animation)",
                "main_picture": {...}
            }
        },
...


The NSFW parameter is poorly implemented. Each anime has a nsfw field that can either be white (safe for work), gray (may not be safe for work), or black (not safe for work).

By default, all new entries are marked as gray, and a DB moderator has to manually set it to the appropriate value. Many SFW series are still marked as gray, hidden from search results.

I suggest you add the nsfw=true parameter to all your queries in the future.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Sep 11, 2023 5:33 AM
Offline
Jan 2017
3
Hey, I need a bit of help (I know kinda old thread sorry)... I am trying to fetch the data in a React app but I get an error, could anyone show me an example on how to create the fetch in a React UseEffect?
Sep 11, 2023 7:56 AM
四十二

Offline
Mar 2016
467
@BorisForis: Hi! I guess that you're trying to call the API straight from your web page. Unfortunately, you cannot do that since the API doesn't return the CORS headers required to call it directly from your browser.

There's no easy solution and it should be fixed by MAL. The usual workaround is to have some kind of middleware that can fix this for you. For example, a local application, a serverless function, a web proxy, or a remote server.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Sep 11, 2023 8:43 AM
Offline
Jan 2017
3
Reply to ZeroCrystal
@BorisForis: Hi! I guess that you're trying to call the API straight from your web page. Unfortunately, you cannot do that since the API doesn't return the CORS headers required to call it directly from your browser.

There's no easy solution and it should be fixed by MAL. The usual workaround is to have some kind of middleware that can fix this for you. For example, a local application, a serverless function, a web proxy, or a remote server.
@ZeroCrystal I was hoping for a solution but in the end I ended up using jikan... Btw you don't happen to know what the highest mal_id is do you? So far I've gone as high as 54501
Sep 11, 2023 10:05 AM
四十二

Offline
Mar 2016
467
Reply to BorisForis
@ZeroCrystal I was hoping for a solution but in the end I ended up using jikan... Btw you don't happen to know what the highest mal_id is do you? So far I've gone as high as 54501
BorisForis said:
Btw you don't happen to know what the highest mal_id is do you? So far I've gone as high as 54501

New entries are added every day. Currently, 56626 is the latest ID.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Sep 12, 2023 1:31 AM
Offline
Jan 2017
3
Thank you so much
Sep 20, 2023 7:26 AM
Offline
May 2022
1
It's working but I don't understand how to get Auth2.0 work. Specially code_challanged parameter
Sep 21, 2023 1:20 PM
四十二

Offline
Mar 2016
467
Reply to SuperDenZ
It's working but I don't understand how to get Auth2.0 work. Specially code_challanged parameter
@SuperDenZ Hi! The Code Challenge must be equal to your Client Verifier. You can take a look at my guide if you need help.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Jan 30, 2024 8:54 AM
Offline
Oct 2023
3
How can we apply this on android while using retrofit?
Jan 30, 2024 3:03 PM
四十二

Offline
Mar 2016
467
Reply to oolyvi
How can we apply this on android while using retrofit?
@oolyvi Hi! I never used Retrofit before but, reading the documentation, it should be quite easy to accomplish.

Go here and scroll down till you reach the Header Manipulation section.
You should do something very close to that example: add the X-MAL-CLIENT-ID header, as explained in the first post, and it should work.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Jan 30, 2024 9:04 PM
Offline
Oct 2023
3
Reply to ZeroCrystal
@oolyvi Hi! I never used Retrofit before but, reading the documentation, it should be quite easy to accomplish.

Go here and scroll down till you reach the Header Manipulation section.
You should do something very close to that example: add the X-MAL-CLIENT-ID header, as explained in the first post, and it should work.
@ZeroCrystal I wrote something like this, but doesn't work

@Headers("X-MAL-CLIENT-ID: $CLIENT_ID")
    @GET("/v2/anime/season/{year}/{season}")
    suspend fun getSeasonalAnimes(
        @Query("year") year: Int,
        @Query("season") season: String,
    ): Response<SeasonalAnimes>
Jan 31, 2024 5:56 AM
四十二

Offline
Mar 2016
467
Reply to oolyvi
@ZeroCrystal I wrote something like this, but doesn't work

@Headers("X-MAL-CLIENT-ID: $CLIENT_ID")
    @GET("/v2/anime/season/{year}/{season}")
    suspend fun getSeasonalAnimes(
        @Query("year") year: Int,
        @Query("season") season: String,
    ): Response<SeasonalAnimes>
@oolyvi What kind of error did you get?
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Jan 31, 2024 7:19 AM
Offline
Oct 2023
3
Reply to ZeroCrystal
@oolyvi What kind of error did you get?
@ZeroCrystal I wrote this and now it works:
@GET("/v2/anime/season/{year}/{season}")
    suspend fun getSeasonalAnimes(
        @Header("X-MAL-CLIENT-ID") clientId: String,
        @Path("year") year: Int,
        @Path("season") season: String,
        @Query("limit") limit: Int
    ): Response<SeasonalAnimes>
Jan 31, 2024 7:40 AM
四十二

Offline
Mar 2016
467
Great.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Oct 7, 2024 10:07 AM
Offline
Jul 2024
1
Hello, I have got a problem.

I want to access public information but if gives me a 403 forbidden error.

I run the code on a Firebase Cloud Function.




export const myanimelist = functions.https.onRequest((request, response) => {
    const url = "https://api.myanimelist.net/v2/anime?q=one&limit=4";

    fetch(url)
        .then((response) => {
            if (!response.ok) {
                throw new Error("Network response was not ok" +
                    response.statusText);
            }
            return response.json();
        })
        .then((data) => {
            console.log(data);
            response.json(data);
        })
        .catch((error) => {
            console.error("Error:", error);
            response.status(500).send("Error fetching MAL data");
        });
});



Could please anyone help me? Thank you very much
jajaja09087Oct 7, 2024 10:16 AM
Oct 8, 2024 5:06 AM
四十二

Offline
Mar 2016
467
Reply to jajaja09087
Hello, I have got a problem.

I want to access public information but if gives me a 403 forbidden error.

I run the code on a Firebase Cloud Function.




export const myanimelist = functions.https.onRequest((request, response) => {
    const url = "https://api.myanimelist.net/v2/anime?q=one&limit=4";

    fetch(url)
        .then((response) => {
            if (!response.ok) {
                throw new Error("Network response was not ok" +
                    response.statusText);
            }
            return response.json();
        })
        .then((data) => {
            console.log(data);
            response.json(data);
        })
        .catch((error) => {
            console.error("Error:", error);
            response.status(500).send("Error fetching MAL data");
        });
});



Could please anyone help me? Thank you very much
@jajaja09087 Hi! When you want to call the public endpoints, you must pass your Client ID as part of the HTTP headers. Like so:

fetch(url, {headers: {"X-MAL-CLIENT-ID": "your-client-id-here"}})
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Oct 30, 2024 8:21 AM
Offline
Jan 2008
2
Hello, I have a problem trying to use the API : https://i.imgur.com/6entWso.png

My console.log does send the correct ID. I've tried in postman without issue, and it's working.
I had to add a "no-cors" mode at some point because it kept me out for some reasons (still no understanding why thou).

But I still get 403 while postman isn't getting any.

For context I'm using electron, and I'm a beginner with this environnement so I'm not sure where the error could come from.

Oct 30, 2024 9:05 AM
四十二

Offline
Mar 2016
467
Reply to Kobaru
Hello, I have a problem trying to use the API : https://i.imgur.com/6entWso.png

My console.log does send the correct ID. I've tried in postman without issue, and it's working.
I had to add a "no-cors" mode at some point because it kept me out for some reasons (still no understanding why thou).

But I still get 403 while postman isn't getting any.

For context I'm using electron, and I'm a beginner with this environnement so I'm not sure where the error could come from.

@Kobaru Hi! By default, Electron enforces the same CORS checks of web browsers. That's why it works on Postman or in any other client that is not a browser.
The no-cors mode doesn't "disable" CORS checks and you should probably remove it.

Adding a callback to onHeadersReceived should fix your problem.
Try following the procedure suggested by this article:
https://pratikpc.medium.com/bypassing-cors-with-electron-ab7eaf331605
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Oct 30, 2024 10:22 AM
Offline
Jan 2008
2
Reply to ZeroCrystal
@Kobaru Hi! By default, Electron enforces the same CORS checks of web browsers. That's why it works on Postman or in any other client that is not a browser.
The no-cors mode doesn't "disable" CORS checks and you should probably remove it.

Adding a callback to onHeadersReceived should fix your problem.
Try following the procedure suggested by this article:
https://pratikpc.medium.com/bypassing-cors-with-electron-ab7eaf331605
@ZeroCrystal Hi 👋

First, thx for the fast reply !
I tried it as the post offered but now I get this error :

https://i.imgur.com/jKhTExJ.png

here is my code for more context :

const handleSearch = useCallback(
    async () => {
      console.log('Searching', value)
      console.log('Client ID', clientID)

      const baseURL = 'https://api.myanimelist.net/v2/anime'
      const myHeaders = new Headers({
        "X-MAL-CLIENT-ID": clientID
      })

      const requestOptions = {
        // mode: 'no-cors',
        method: "GET",
        headers: myHeaders,
      } as RequestInit

      try {
        const response = await fetch(`${baseURL}?q=${value}&limit=4`, requestOptions)
        if (!response.ok) {
          throw new Error(`Response status: ${response.status}`)
        }
        const json = await response.json()
        console.log(json)
      } catch (error) {
        console.error(error)
      }
    },
    [value],
  )


Edit :

Someone on the unofficial discord told me "You can't do it via a browser." which would makes sens to anybody with a proper backend background, that I don't have.

So for now my solution will be to add
webSecurity: false
to my BrowserWindow configuration. It should do the trick to prototype in a local env.

He said that I had to do a proxy server or backend to achieve what I wanna do, but I don't know at all how to start with that so far... So I'll just leave it at that and come back to the problem later once my prototype is well and running
KobaruOct 30, 2024 12:42 PM
Oct 31, 2024 9:32 AM
四十二

Offline
Mar 2016
467
Reply to Kobaru
@ZeroCrystal Hi 👋

First, thx for the fast reply !
I tried it as the post offered but now I get this error :

https://i.imgur.com/jKhTExJ.png

here is my code for more context :

const handleSearch = useCallback(
    async () => {
      console.log('Searching', value)
      console.log('Client ID', clientID)

      const baseURL = 'https://api.myanimelist.net/v2/anime'
      const myHeaders = new Headers({
        "X-MAL-CLIENT-ID": clientID
      })

      const requestOptions = {
        // mode: 'no-cors',
        method: "GET",
        headers: myHeaders,
      } as RequestInit

      try {
        const response = await fetch(`${baseURL}?q=${value}&limit=4`, requestOptions)
        if (!response.ok) {
          throw new Error(`Response status: ${response.status}`)
        }
        const json = await response.json()
        console.log(json)
      } catch (error) {
        console.error(error)
      }
    },
    [value],
  )


Edit :

Someone on the unofficial discord told me "You can't do it via a browser." which would makes sens to anybody with a proper backend background, that I don't have.

So for now my solution will be to add
webSecurity: false
to my BrowserWindow configuration. It should do the trick to prototype in a local env.

He said that I had to do a proxy server or backend to achieve what I wanna do, but I don't know at all how to start with that so far... So I'll just leave it at that and come back to the problem later once my prototype is well and running
@Kobaru Did you set up your application to rewrite all response headers adding Access-Control-Allow-Origin: *? That would be the best way to solve the issue. I'm not a fan of disabling webSecurity, but it's good enough as a starting point.

Electron is both a browser engine and a JS backend, so you can do things a web browser cannot accomplish, like bypassing CORS limitations.
You don't need an additional backend.
HTCPCP/1.0  ★ MetaMAL  ★ Picture credits: 第三世界のじょんぺり & 1041uuu
Reply Disabled for Non-Club Members
Pages (2) « 1 [2]

More topics from this board

» [FEATURE REQUEST] Bulk requests & add fields param to users watchlist

KibbeWater - Feb 13

0 by KibbeWater »»
Feb 13, 8:38 AM

» How to get author name?

EdibleMuffin - Feb 12

0 by EdibleMuffin »»
Feb 12, 9:35 PM

» Too many request even with 10 seconds delay

Joaoniespodzinsk - Jan 31

1 by ZeroCrystal »»
Feb 4, 11:04 AM

» Anime Field: Streaming Platforms

SeeYouLaterSpace - Feb 10, 2023

2 by IridescentJaune »»
Jan 30, 1:21 PM

» Allowed usage or not ?

dczerwon - Jan 13

0 by dczerwon »»
Jan 13, 3:07 AM
It’s time to ditch the text file.
Keep track of your anime easily by creating your own list.
Sign Up Login