188

I have an options page where the user can define certain options and it saves it in localStorage: options.html

Now, I also have a content script that needs to get the options that were defined in the options.html page, but when I try to access localStorage from the content script, it doesn't return the value from the options page.

How do I make my content script get values from localStorage, from the options page or even the background page?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
user476214
  • 1,881
  • 2
  • 12
  • 3
  • 2
    Related: http://stackoverflow.com/questions/3033829/google-chrome-extension-local-storage – Shay Erlichmen Oct 14 '10 at 21:27
  • 1
    Related: http://stackoverflow.com/questions/4224039/chrome-extension-with-cloud-storage – Jason Jul 19 '12 at 05:30
  • 1
    Related: http://stackoverflow.com/questions/39768005/single-data-store-offline-locally-for-both-a-web-site-and-an-extension-in-chrome?noredirect=1#comment66832892_39768005 – super1ha1 Sep 30 '16 at 02:28

4 Answers4

274

Update 2016:

Google Chrome released the storage API: https://developer.chrome.com/docs/extensions/reference/storage/

It is pretty easy to use like the other Chrome APIs and you can use it from any page context within Chrome.

    // Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });

To use it, make sure you define it in the manifest:

    "permissions": [
      "storage"
    ],

There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"

Using native localStorage (old reply from 2011)

Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.

Now, to let your content script to read your extension storage (where you set them from your options page), you need to use extension message passing.

The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension localStorage:

contentscript.js

chrome.runtime.sendMessage({method: "getStatus"}, function(response) {
  console.log(response.status);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});

You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.

I hope that helped solve your problem.

To be fancy and generic ...

contentscript.js

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});
vigri
  • 475
  • 1
  • 5
  • 16
Mohamed Mansour
  • 39,445
  • 10
  • 116
  • 90
  • 1
    Obviously, request could also be {method:'getStorage', key: 'status'}, and the listener would respond with the corresponding data. – J.C. Inacio May 28 '11 at 01:00
  • What if I want everything from the localStorage to be transferred to the extension? Can I write `sendResponse({data: localStorage});` ? – Bibhas Debnath Jul 20 '11 at 19:23
  • I'm a bit confused. I want data from my options page to be available at background.html page.. So I make a request from Background page to the contentscript? and contentscript can send back the localStorage data? See this -> http://pastebin.com/xtFexFtc .. Am I doing it right? – Bibhas Debnath Jul 23 '11 at 08:01
  • 8
    The background page and options page belong to the same extension context, so you don't need content scripts or messaging. You can call `localStorage` directly from the options page or use `chrome.extension.getBackgroundPage` from the options page. – Mohamed Mansour Jul 23 '11 at 12:43
  • 1
    Thats strange. I'm setting few options in options page and creating context menus based on them in background page. The thing is, if I set a variable in localStorage from options page, it doesnt get reflected to the background page immediately(i.e. No new contextmenu), unless I disable and re-enable the extension. Any reason you can think of? – Bibhas Debnath Jul 23 '11 at 16:57
  • @MohamedMansour I'm not sure if this is still valid 2 years later, but should `background.html` be `options.html` instead? I'm still having trouble with this. – TankorSmash Sep 07 '12 at 03:37
  • I believe Chrome changed the extension design so it should be background.js, not options because options page only lives when you activate it and disposes once you close it. – Mohamed Mansour Jun 16 '13 at 09:19
  • Thanks @OrangeTux, woah, it has been two years since I wrote this answer :) I just updated it to the new API, thanks – Mohamed Mansour Dec 28 '13 at 20:35
  • @MohamedMansour : do you have any recommendation for this question http://stackoverflow.com/questions/39768005/single-data-store-offline-locally-for-both-a-web-site-and-an-extension-in-chrome?noredirect=1#comment66832892_39768005 – super1ha1 Sep 30 '16 at 02:30
  • Use your method ContentScript can read localStorage of background page now ! – sonichy Aug 31 '17 at 09:23
  • @MohamedMansour, What about all-or-nothing **transactions**? – Pacerier Sep 08 '17 at 06:23
  • For some reason, I still had to use the old answer from 2011. But I am getting localStorage is not defined . Anyone facing the same issue ? – TSR Oct 11 '22 at 02:36
53

Sometimes it may be better to use chrome.storage API. It's better then localStorage because you can:

  • store information from your content script without the need for message passing between content script and extension;
  • store your data as JavaScript objects without serializing them to JSON (localStorage only stores strings).

Here's a simple code demonstrating the use of chrome.storage. Content script gets the url of visited page and timestamp and stores it, popup.js gets it from storage area.

content_script.js

(function () {
    var visited = window.location.href;
    var time = +new Date();
    chrome.storage.sync.set({'visitedPages':{pageUrl:visited,time:time}}, function () {
        console.log("Just visited",visited)
    });
})();

popup.js

(function () {
    chrome.storage.onChanged.addListener(function (changes,areaName) {
        console.log("New item in storage",changes.visitedPages.newValue);
    })
})();

"Changes" here is an object that contains old and new value for a given key. "AreaName" argument refers to name of storage area, either 'local', 'sync' or 'managed'.

Remember to declare storage permission in manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Sebastian
  • 3,322
  • 22
  • 34
Pawel Miech
  • 7,742
  • 4
  • 36
  • 57
  • 1
    The `onChanged` event already provides the data in the `changes` object. Further, pay special attention to the `namespace` of the `onChanged` event. If you store something using `chrome.storage.local.set`, then the `onChanged` event is triggered, but reading using `chrome.storage.sync.get` makes little sense. – Rob W Jan 12 '14 at 11:13
  • Yes you're right, edited my answer. Obviously you can use chrome.storage.sync.get in other scenarios, but here it is indeed redundant. – Pawel Miech Jan 12 '14 at 11:26
  • 1
    In response to revision 5 of your answer: `changes.visitedPages` will be undefined if `visitedPages` has not been changed. Wrap the line in `if (changes.visitedPages) { ... }` to solve this problem. – Rob W Jan 12 '14 at 13:41
  • If I have set Google Auth in some auth.js and content_script should run If I get user details, how should I manage the message passing for both files? – Sudhir Kaushik Jun 13 '23 at 19:05
8

Another option would be to use the chromestorage API. This allows storage of user data with optional syncing across sessions.

One downside is that it is asynchronous.

https://developer.chrome.com/extensions/storage.html

Pawel Miech
  • 7,742
  • 4
  • 36
  • 57
Jason
  • 9,408
  • 5
  • 36
  • 36
6

[For manifest v3]

You can execute a script that returns localstorage items from the webpage. This script can be executed from popup or background service worker.

Add this line in manifest.json:

"permissions": ["scripting"]


 let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })

 // Execute script in the current tab
  const fromPageLocalStore = await chrome.scripting.executeScript({
    target: { tabId: tabId },
    func: () => {
      return JSON.stringify(localStorage)
    }
  })

  const localStorageItems = JSON.parse(fromPageLocalStore[0].result)
GorvGoyl
  • 42,508
  • 29
  • 229
  • 225