Hi, I was wondering if there was a way to store some fields in the browser local storage of a client and access them through streamlit. I want to be able to repopulate certain fields if the user closes my form and opens it after some time.
If this isn’t feasible is using cookies my best option and is there a good way of setting and updating cookie keys via streamlit?
Hi @pramodith, welcome to the forum. There’s st.experimental_set_query_params and st.experimental_get_query_params that allows you to send field information via query parameters in the browser’s URL bar.
Hey @dataprofessor thanks for the pointer but I’m afraid I’m looking for something else. In my application the user should be able to close the url to my application, but on returning certain fields of the user need to be restored. The application does not have a login feature so we want to store these fields in the clients browser via local storage or through cookies.
Sir, I had a similar doubt. Can these be used for this? Or is there another way? I have not deployed my app yet, if I deploy it, will I be able to keep track of some ss variables from all the open instances at a central location?
However, when I try running this I get the following error :
streamlit.errors.DuplicateWidgetID: There are multiple identical st.extra_streamlit_components.CookieManager.cookie_manager widgets with key='set'.
To fix this, please make sure that the key argument is unique for
each st.extra_streamlit_components.CookieManager.cookie_manager you create.
I’m not sure which key is not unique in this case.
I’ve just built a synchronous way to access localStorage from Streamlit using websockets (streamlit-ws-localstorage), feel free to try it out.
I struggled for a couple of days with localStorage access (and authentication), and thought it would be easier to build a websocket based synchronous communication itself. The code is simple, just import the module and use it like this:
import streamlit as st
from streamlit_ws_localstorage import injectWebsocketCode, getOrCreateUID
# Main call to the api, returns a communication object
conn = injectWebsocketCode(hostPort='linode.liquidco.in', uid=getOrCreateUID())
st.write('setting into localStorage')
ret = conn.setLocalStorageVal(key='k1', val='v1')
st.write('ret: ' + ret)
st.write('getting from localStorage')
ret = conn.getLocalStorageVal(key='k1')
st.write('ret: ' + ret)
Here is a demo of fetching saved info in the browser:
the “key” means the wiget_id ,not key in dict. when you use the wiget like get,set,delete, you should not use same Key, you can apply like this:key=“0”, “1”,“2”,etc,it works
I tried your code verbatim. But it throws an error:
ssl.SSLCertVerificationError: This app has encountered an error. The original error message is redacted to prevent data leaks. Full error details have been recorded in the logs (if you're on Streamlit Cloud, click on 'Manage app' in the lower right of your app).
Traceback:
File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 535, in _run_script
exec(code, module.__dict__)
File "/mount/src/xxxxx/xxxxx.py", line 8, in <module>
ret = conn.setLocalStorageVal(key='k1', val='v1')
File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit_ws_localstorage/__init__.py", line 99, in setLocalStorageVal
result = self.sendCommand(json.dumps({ 'cmd': 'localStorage_set_key', 'key': key, 'val': val }))
File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit_ws_localstorage/__init__.py", line 90, in sendCommand
self.loop.run_until_complete(query(future1))
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
return future.result()
File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit_ws_localstorage/__init__.py", line 80, in query
async with websockets.connect("wss://" + self.hostPort + "/?uid=" + self.uid, ssl=ssl_context) as ws:
File "/home/adminuser/venv/lib/python3.9/site-packages/websockets/legacy/client.py", line 629, in __aenter__
return await self
File "/home/adminuser/venv/lib/python3.9/site-packages/websockets/legacy/client.py", line 647, in __await_impl_timeout__
return await self.__await_impl__()
File "/home/adminuser/venv/lib/python3.9/site-packages/websockets/legacy/client.py", line 651, in __await_impl__
_transport, _protocol = await self._create_connection()
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1090, in create_connection
transport, protocol = await self._create_connection_transport(
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1120, in _create_connection_transport
await waiter
File "/usr/local/lib/python3.9/asyncio/sslproto.py", line 534, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "/usr/local/lib/python3.9/asyncio/sslproto.py", line 188, in feed_ssldata
self._sslobj.do_handshake()
File "/usr/local/lib/python3.9/ssl.py", line 945, in do_handshake
self._sslobj.do_handshake()
from streamlit_javascript import st_javascript
def local_storage_get(key):
return st_javascript(f"localStorage.getItem('{key}');")
def local_storage_set(key, value):
value = json.dumps(value, ensure_ascii=False)
return st_javascript(f"localStorage.setItem('{key}', JSON.stringify('{value}');")
The only problem was, that due to asynchronous nature of streamlit components, st_javascript did not provide return value of js code immidiatelly. Instead, it reloads some number of times before providing the value. And in case of None, you just don’t know if it returns empty value because you js code returns null or because the code execution hasn’t finished yet. So, the following code didn’t work
if "token" not in st.session_state:
st.session_state.token = local_storage_get("token")
It just saved 0 - initial value of st_javascript component.
So, i build my own version of this lib, that allows distinguishing between “not ready yet” and “returns none” states.
Brief explanation:
It returns [] if the code execution is in progress and [] if it finishes. So, you can just st.stop() until result is not empty or for unblocking case, just check it before setting session_state value
if "token" not in st.session_state:
if result := local_storage_get("token"):
st.session_state.token = result[0]
Hey @toolittlecakes I wanted to try this out but both links in your post seem to go to the original repo? is there a link to your fork somewhere? Thanks!
EDIT: Nvm, i found it from guessing your github username for anyone else curious:
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.