CORS error when creating/updating study material

I want to create/update a study material from a Tapermonkey script. If I paste the following example

var apiToken = '<api_token_here>';
var apiEndpointPath = 'study_materials';
var requestHeaders =
  new Headers({
    'Wanikani-Revision': '20170710',
    Authorization: 'Bearer ' + apiToken,
  });
var apiEndpoint =
  new Request('https://api.wanikani.com/v2/' + apiEndpointPath, {
    method: 'POST',
    headers: requestHeaders,
    body: {
      "study_material": {
        "subject_id": 2,
        "meaning_note": "The two grounds is too much",
        "reading_note": "This is tsu much",
        "meaning_synonyms": [
          "double"
        ]
      }
    }
  });

fetch(apiEndpoint)
  .then(response => response.json())
  .then(responseBody => console.log(responseBody));

from https://docs.api.wanikani.com/20170710/?javascript#create-a-study-material in the Chrome console after visiting https://www.wanikani.com/ (and substitute in my API key) I get the following error:

Access to fetch at 'https://api.wanikani.com/v2/study_materials' from origin 'https://www.wanikani.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
builder.js:691 POST https://api.wanikani.com/v2/study_materials net::ERR_FAILED
(anonymous) @ builder.js:691
(anonymous) @ VM48:24
(index):1 

I get the same error if I run the code in a Tapermonkey script like the following.

// ==UserScript==
// @name         WaniKani Create Study Material Test
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.wanikani.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // SAME CODE HERE
})();

I do not get a CORS error when using the API to get a study material or subject data from www.wanikani.com. I only have a problem with creating/updating. Is this intentional? Is there a reason this couldn’t be allowed? Why do I not get CORS errors when making other API requests?

I can use GM_xmlhttpRequest to work around the problem, but I would rather not since it adds friction by asking the user to allow the function.

I don’t know why you get CORS errors but I can tell you I don’t get them when I access study materials using wkof. Maybe this is a suitable workaround for you.

2 Likes

The errors occur when trying to create or update study materials. I looked at this code and it seems to only support making GET requests. Are you making any POST or PUT requests?

1 Like

No I am not. I am afraid I can’t help you with POST or PUT requests.

Blockquote

You don’t get the CORS errors on other API requests because those qualify as “simple requests” that are safelisted from CORS restrictions.

I can use GM_xmlhttpRequest to work around the problem, but I would rather not since it adds friction by asking the user to allow the function.

This will probably be your best bet. The only other option that I can think of is to spin up a node server somewhere that skips CORS restrictions using the Access-Control-Allow-Origin header and then have your script use it to proxy the requests to the WK API.

1 Like

OK, thanks for taking a look anyway!

1 Like

I see. Thanks for the info!

I thought perhaps the WaniKani engineers could add an exception for requests made from www.wanikani.com in order to support userscripts since they also control that domain. Could there be any negative consequences?

I also saw when you edit a note normally it makes a non-API request. Perhaps it is possible to imitate those requests in JavaScript.

One negative consequence would be that a malicious userscript could modify users’ data in unwanted ways, reset their level, etc. without warning.

I’ve not tried it yet, but according to this post you can avoid the prompt when using GM_xmlhttpRequest. If I understand correctly, then I think userscripts already pose this risk.

1 Like