'Strange behaiver of localStorage with Puppeteer

Im trying to save the localStorage to a variable outside of the page.evaluate(). But it seems that i cant do it. Below is the code im trying to use and outputs of consloe.log()'s , how i can make it to work and save the localStorage to a variable ? Inside the callback i can see the localStorage, but it dont act regular as getItem isnt working.

I'm trying several ways to get the data but none seems to work... any idea why?

await page.click("[id=Login-button]");

let savedLocalStorage = "";

const result = await page.evaluate(savedLocalStorage => {
console.log(localStorage); //output: {AUTH: 12345}

console.log(localStorage.key(0)); //output: null

console.log(localStorage.getItem("AUTH")); //output: null

localStorage.setItem("Test", "1234"); //working

console.log(localStorage); //output: {AUTH: 12345, Test: 1234}

savedLocalStorage = localStorage;

//savedLocalStorage = localStorage.AUTH; - same result as savedLocalStorage = localStorage;

return localStorage;
}, savedLocalStorage);

console.log(savedLocalStorage); //output: ""

console.log(result); //output: {}


Solution 1:[1]

Try serializing the data,:

    async function saveLocalStorage(page, filePath) {
      const json = await page.evaluate(() => {
        const json = {};
        for (let i = 0; i < localStorage.length; i++) {
          const key = localStorage.key(i);
          json[key] = localStorage.getItem(key);
        }
        return json;
      });
      fs.writeFileSync(filePath, 'utf8', JSON.stringify(json));
    }

    async function restoreLocalStorage(page, filePath) {
      const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
      await page.evaluate(json => {
        localStorage.clear();
        for (let key in json)
          localStorage.setItem(key, json[key]);
      }, json);
    }

https://github.com/GoogleChrome/puppeteer/issues/727

Solution 2:[2]

First of all, you won't be able to pass savedLocalStorage as a reference. The script inside the evaluate will get a serialized copy of that variable.

Regarding the result. Puppetter won't return a serialized localStorage but a pointer (JSHandle) to the object inside the browser. It's basically a puppeteer object you can pass to another evaluate function, in this case "as a reference".

What you could do is serialize the localStorage and then parse it on the other side.

const result = await page.evaluate(() => {
  localStorage.setItem("Test", "1234"); //working
  return JSON.stringify(localStorage);
});

console.log(JSON.parse(result));
<!DOCTYPE html>
<html>
  <head>
    <title>console.log test</title>
  </head>
  <body>
    <script>
      localStorage.setItem("AUTH", 12345);
    </script>
  </body>
</html>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 fortunee
Solution 2