Skip to content

Instantly share code, notes, and snippets.

@raineorshine
Last active December 1, 2021 17:02
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save raineorshine/68fab3b4b96f54b808a858217b83fe94 to your computer and use it in GitHub Desktop.
Save raineorshine/68fab3b4b96f54b808a858217b83fe94 to your computer and use it in GitHub Desktop.
Export Memrise course words to CSV. There is also a Chrome Extension: https://chrome.google.com/webstore/detail/memrise-export/hcllgkpmoiolndnhmbdceffaidjmkoam
/*
UPDATE: This is now a Chrome Extension: https://chrome.google.com/webstore/detail/memrise-export/hcllgkpmoiolndnhmbdceffaidjmkoam
Source Code: https://github.com/raineorshine/memrise-export
Export Memrise course words to CSV (technically TSV, or "tab separated file", but it is effectively the same).
1. Log into Memrise.
2. Navigate to the course page you would like to export (e.g. https://app.memrise.com/course/2156672/german-random-01/).
3. Open the browser's Developer Console (https://support.airtable.com/hc/en-us/articles/232313848-How-to-open-the-developer-console)
4. Paste the below script into the console and hit enter.
5. After all pages have been loaded, copy and paste the final word list into spreadsheet.
*/
(() => {
/** Returns a Promise of a list of all words in a course. */
function getWords(courseId, level=0) {
if (level > 0) {
console.log(`Loading Page ${level}...`)
}
const url = `${location.origin}/ajax/session/?course_id=${courseId}&level_index=${level + 1}&session_slug=preview`
return fetch(url, { credentials: 'same-origin' })
// parse response
.then(res => res.ok
? res.json()
// map results
.then(data => {
const { name, num_things, num_levels } = data.session.course
if (level === 0) {
console.log(`Exporting ${num_things} words (${num_levels} pages) from "${name}"`)
}
return data.learnables.map(row => ({
original: row.item.value,
translation: row.definition.value
}))
})
.then(words => {
// RECURSION
return getWords(courseId, level + 1)
.then(words.concat.bind(words))
})
// print an error if they are not logged in
: res.status > 400 ? res.text().then(text => {
console.error(`Error (${res.status}): ${text}`)
return []
})
: []
)
.catch(err => {
console.error(err)
return []
})
}
// parse the course id
const courseId = location.href.slice(30).match(/\d+/)[0]
// get the words
getWords(courseId).then(words => {
if (words.length > 0) {
const output = words.map(word => `${word.translation}\t${word.original}\n`).join('')
console.log(output)
}
})
})()
@scottharvey
Copy link

Works well, you might want to detect whether to use http or https to prevent console errors. 👍

@Andulien
Copy link

Andulien commented Jul 6, 2017

Sadly this script doesn't work for me :( Is there any possibility to get it fix or tell me what I maybe did wrong?

I went to: https://www.memrise.com/course/95191/minna-no-nihongo-i-grammar/
Opened the consol and pasted your script. (I also edited the http to https else it give a whole bunch of other errors)
Hit enter.
Then I get the following error:

VM245:34 TypeError: Cannot convert undefined or null to object
at Function.keys ()
at res.status.res.json.then.data (:22:29)
at
VM245:45 0 words

@rhegler19
Copy link

@Andulien
You have to sign in to memrise; then the script will work.

@v11viktor
Copy link

libs-a63ec21310.js:15 Mixed Content: The page at 'https://www.memrise.com/course/183314/3000-leggyakoribb-angol-szo-audio/' was loaded over HTTPS, but requested an insecure resource 'http://www.memrise.com/ajax/session/?course_id=183314&level_index=1&session_slug=preview'. This request has been blocked; the content must be served over HTTPS.
libs-a63ec21310.js:14 TypeError: Failed to fetch
t.(anonymous function) @ libs-a63ec21310.js:14
fetch.then.catch.err @ VM1504:25
Promise rejected (async)
getWords @ VM1504:24
(anonymous) @ VM1504:33
(anonymous) @ VM1504:42
libs-a63ec21310.js:14 0 words

Error.

@johan456789
Copy link

Could someone help me fix this? I'd already logged in to memrise and change the url to https.

and then I got the error...
TypeError: undefined is not an object (evaluating 'Object.keys(data.things)')

screen shot 2017-12-25 at 03 54 37

@FahimF
Copy link

FahimF commented May 7, 2018

The following updated version works at the moment, but if the folks at Memrise change the output data format, then it might stop working again ...

(() => {

  function getWords(courseId, level) {
    const url = `https://www.memrise.com/ajax/session/?course_id=${courseId}&level_index=${level}&session_slug=preview`
    console.log('Fetching words from ' + url)
    return fetch(url, { credentials: 'same-origin' })
      // parse response
      .then(res => {
        return res.status === 200
          ? res.json()
            // map results
            .then(data => {
              return data.learnables.map(row => ({
                original: row.item.value,
                translation: row.definition.value
              }))
            })
            .then(words => {
              return getWords(courseId, level + 1)
                .then(words.concat.bind(words))
            })
          : []
    })
    .catch(err => {
      console.error(err)
      return []
    })
  }

  // fetch
  const start = 1
  const courseId = location.href.slice(30).match(/\d+/)[0] 
  getWords(courseId, start)
    // format as csv
    .then(words => {
      console.log(words.length + ' words')
      return words.map(word => word.translation + '\t' + word.original + '\n').join('')
    })
    // print
    .then(console.log)

})()

@dadadidudu
Copy link

the updated version works great, thanks!

@wyun
Copy link

wyun commented Jun 22, 2018

Thanks! Excellent script. I used it to export words from memrise into tinycards. TinyCard's web interface has a grid icon, click on it, you can paste the output directly in there. Quite convenient. Thanks!

The only change I need to make is to swap word.translation and word.original on one of the last few lines.

(() => {

  function getWords(courseId, level) {
    const url = `https://www.memrise.com/ajax/session/?course_id=${courseId}&level_index=${level}&session_slug=preview`
    console.log('Fetching words from ' + url)
    return fetch(url, { credentials: 'same-origin' })
      // parse response
      .then(res => {
        return res.status === 200
          ? res.json()
            // map results
            .then(data => {
              return data.learnables.map(row => ({
                original: row.item.value,
                translation: row.definition.value
              }))
            })
            .then(words => {
              return getWords(courseId, level + 1)
                .then(words.concat.bind(words))
            })
          : []
    })
    .catch(err => {
      console.error(err)
      return []
    })
  }

  // fetch
  const start = 1
  const courseId = location.href.slice(30).match(/\d+/)[0] 
  getWords(courseId, start)
    // format as csv
    .then(words => {
      console.log(words.length + ' words')
      return words.map(word => word.original + '\t' + word.translation  + '\n').join('')
    })
    // print
    .then(console.log)

})()

@ak1dd
Copy link

ak1dd commented Jul 12, 2018

Hi. I am getting a new error as of July 12, 2018. I am using the latest script in this thread and am logged in to memrise. Can someone help me?

image

@rudhraksh
Copy link

Thank you very much for this! The updated code worked like a charm.
I had created a course with vocabulary for my class, but was unable to download my own course.
I had also filled in the plural and inflected form columns

image

Is it possible for us to download that column as well?

@Cobradabest
Copy link

I'm getting "SyntaxError: unexpected token: identifier" when I try to use the script.

@Kaputtendorf1
Copy link

The script works! thanks a lot.
one question, is there a similar way to extract audio from a memrise course?

@bentzi18
Copy link

hi i am very new to this so might be doing something wrong that is obvious to some. this is what i am seeing when i copy that code into the console. Any help would be great. Thanx!
Screen Shot 2019-05-28 at 12 33 57 pm

@Yinyue93
Copy link

Hello. FahimF's version of the script had been working for me, but now it seems it doesn't work anymore. This is the message I get:

Access to fetch at 'https://www.memrise.com/ajax/session/?course_id=5583840&level_index=1&session_slug=preview' from origin 'https://app.memrise.com' has been blocked by CORS policy: 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.

Any help please? This script is very useful for me and I would love to keep using it. Thanks in advance

@raineorshine
Copy link
Author

raineorshine commented Aug 19, 2020

@Yinyue93 Glad you asked! The CORS policy prevents fetching data from other domains. Since Memrise switched from www.memrise.com to app.memrise.com, the CORS policy thought it was trying to access a different domain and blocked it. Changing the URL in the script fixes it. I've updated the original gist. Try it now!

@Yinyue93
Copy link

@raineorshine Thanks for your quick reply :) but for some reason it still doesn't work for me. I get this:

TypeError: Cannot convert undefined or null to object
at Function.keys ()
at :13:29

Why could the reason for the error be...?

@raineorshine
Copy link
Author

@Yinyue93 I'm not sure. Are you logged in? If so, is there any more information with the error message? It's not enough for me to see where the problem might be.

@Yinyue93
Copy link

@raineorshine Did you update the script again? I restarted the browser and it worked now. Thank you very much! :)

@raineorshine
Copy link
Author

@Yinyue93 Yay! I'm glad the new version works.

@AniruddhaHumane
Copy link

Hi, Is it possible to export mems too? Mnemonics I mean?

@raineorshine
Copy link
Author

@AniruddhaHumane I'm not sure, where can I find them in Memrise? I've only worked with the course page so far, in which the following data is available:

Course:

{
  "id": 2156672,
  "name": "German Random 01",
  "slug": "german-random-01",
  "url": "/course/2156672/german-random-01/",
  "description": "",
  "photo": "https://static.memrise.com/uploads/course_photos/19881832000190401135248.png",
  "photo_small": "https://static.memrise.com/img/100sqf/from/uploads/course_photos/19881832000190401135248.png",
  "photo_large": "https://static.memrise.com/img/400sqf/from/uploads/course_photos/19881832000190401135248.png",
  "num_things": 45,
  "num_levels": 2,
  "num_learners": 11,
  "source": {
    "id": 963,
    "slug": "english-us",
    "name": "English (US)",
    "photo": "https://static.memrise.com/uploads/category_photos/us_flag.png",
    "parent_id": 578,
    "index": 0,
    "language_code": "en-US"
  },
  "target": {
    "id": 4,
    "slug": "german-2",
    "name": "German",
    "photo": "https://static.memrise.com/uploads/language_photos/german.png",
    "parent_id": 879,
    "index": 1048,
    "language_code": "de"
  },
  "contains_sample_sentences": false,
  "is_memrise_course": false,
  "num_items_for_review": 0
}"

Words:

{
  "learnable_id": "14170871300354",
  "thing_id": 216230336,
  "item": {
    "kind": "text",
    "value": "immer",
    "label": "German",
    "always_show": false,
    "alternatives": [],
    "style": []
  },
  "definition": {
    "kind": "text",
    "value": "always",
    "label": "English",
    "always_show": false,
    "alternatives": [],
    "style": []
  },
  "confused_answers": [],
  "difficulty": "unknown"
}

@raineorshine
Copy link
Author

@AniruddhaHumane
Copy link

AniruddhaHumane commented Sep 9, 2020

great work @raineorshine! mnemonics are available in the community-made courses and they speed up the learning process a lot. Here's a link to one of the community-made courses that have mnemonics. Apparently I am not able to view them on the website but probably they show it when we start learning or reviewing. I couldn't find any *.jpg/jpeg/png in the JSON that is being parsed too.

@raineorshine
Copy link
Author

@AniruddhaHumane Thanks. I did find the internal API for mems, but it's not clear how we should export them since there are multiple mems per learning item. I invite you to join me in further discussion here: raineorshine/memrise-export#2.

@WiliTest
Copy link

WiliTest commented Apr 2, 2021

The script did not work for me on the console (for this course) but the Chrome Extension did (thank you!). It would be great to export all the mems, but only if it was possible to reimport them on another Memrise course (is it possible?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment