Cookies support in Streamlit!

I’m having a similar experience as many other users reporting here. I too experience the 3x loading as described and inconsistent return of cookies despite trying different ways of trying to get around that.

It’s effectively unusable for me.

Note I have found more luck with streamlit-cookies-manager · PyPI
But this library does not work on safari (macOS or iOS) in my testing. There are some issues with it sometimes initially loading as well.

3 Likes

Hi,

I wrote a set of functions to get server properties, client headers and client cookies.

They use HACKS discussed in these threads:

Please note: this code is unsupported and will break if the Streamlit dev team change their APIs. You’re on your own :melting_face:

import re
import streamlit as st
try:
    # Streamlit >= 1.12.0
    from streamlit.web.server.server import Server
    from streamlit.runtime.runtime import Runtime, SessionInfo
    from streamlit.runtime.scriptrunner import add_script_run_ctx
    # from streamlit.runtime.scriptrunner import get_script_run_ctx
except:
    raise Exception('You must use Streamlit >= v1.12.0')

# Mega hack walking the GC heap.
# Look only for singletons that you know exist for the entire streamlit server lifetime, e.g.: Server and Runtime!!
def st_instance_of_type(type_obj: object) -> object:
    import gc
    st_obj = None
    for obj in gc.get_objects():
        if type(obj) is type_obj:
            st_obj = obj
            break
    return st_obj

def st_server_props():
    st_server = st_instance_of_type(Server)

    st_server_runtime = st_server._runtime
    st_gc_runtime = st_instance_of_type(Runtime)
    assert(st_server_runtime == st_gc_runtime)

    main_script_path = st_server.main_script_path
    browser_is_connected = st_server.browser_is_connected

    return {'st_server_runtime': st_server_runtime, 'st_gc_runtime': st_gc_runtime, 'main_script_path': main_script_path, 'browser_is_connected': browser_is_connected}
    
def st_session_info() -> SessionInfo:
    st_runtime = st_instance_of_type(Runtime)
    # get session id from the current script runner thread
    session_id = add_script_run_ctx().streamlit_script_run_ctx.session_id
    # use the session id to retrieve the session info
    session_info = st_runtime._get_session_info(session_id)
    return session_info

def st_client_headers() -> dict:
    session_info = st_session_info()
    client_headers = session_info.client.request.headers._dict
    return dict(client_headers)

def st_client_cookies() -> dict:
    client_headers = st_client_headers()
    cookies_str = client_headers["Cookie"]
    results = re.findall(r"([\w]+)=([^;]+)", cookies_str)
    cookies = dict(results)
    return cookies

st.subheader('Server Props')
st.write(st_server_props())

st.subheader('Client Headers')
st.write(st_client_headers())

st.subheader('Client Cookies')
st.write(st_client_cookies())

HTH,
Arvindra

6 Likes

This is a good method. Unfortunately, it can only query the current session ID. Once I change the cookie, it still returns the previous value. Thank you

1 Like

Is there a plan to support Streamlit’s new cache functions? st.cache was deprecated, and neither st.cache_data nor st.cache_resource seem to work with this package.
Thanks!

5 Likes

Updated minimum version of Streamlit required by ExtraStreamlitComponents to replace deprecated methods with newer ones, add more control over CookieManager, and fix known bugs. Please upgrade your package to 0.1.60

3 Likes

Hello, I would like to mention another issue with this package. I have an application with a login page and 13 other pages. Hence, each page gets cookies from the browser to check login activity and shows the content or displays an error accordingly. However, I realized after I deployed the website that the CPU usage of the website increased significantly after some time from the deployment, which caused an extreme slowdown. When I redeployed the website, the response time was perfect. However, it slowed down after some time, again. Then, I used memory-profiler to check what was causing this slowdown. The outcome is that this package causes an extreme slowdown in the website. It is so slow that the login page does not show up anymore. How can I solve this problem?

2 Likes

Hi @burakozpoyraz,

Did you tried to save the status of logged user in st.session_state, and then just calling it in every page? Maybe the calling cookies each page is getting the app slower?
Just thinking around this issue.

1 Like

Hi @Mohamed

I am using the cookies manager with following code. my code works in local environment, but i need to deploy my application in a docker container, and surprisingly application is not able to store cookies there, and not even throwing any error.

Could you please help me out.

Thank you.

import extra_streamlit_components as stx
from datetime import datetime, timedelta
import streamlit as st
cookie_manager = stx.CookieManager()


def set_cookie():
    cookie_manager.set("my-cookie", "token-value",
                            expires_at=datetime.now() + timedelta(minutes=5))
    
def delete_cookie():
    cookie_manager.delete("my-cookie")


st.button("Set cookie", on_click=set_cookie)

st.button("Delete cookie", on_click=delete_cookie)
1 Like

Hi everyone! It seems cookies are not persisted when I call .save() method. I’m doing the following:

cookies = EncryptedCookieManager(prefix=COOKIE_PREFIX, password=<>)
cookies["some_key"] = "some_value"
cookies.save()

I’ve tried to call .save() after I set a key and at the end of the streamlit page but none worked. What am I missing? How can I persist cookies so that if I refresh the page or open a new tab they are restored?
If I want to override a previous added value, should I:

cookies.update(some_key="new_value")

?

1 Like

I experience the same issue where the cookie manager won’t work on a Docker container.
Fortunately, there is a new package in the neighborhood:

1 Like

Hey folks, the package has an updated version (0.1.70) including fixing many of the above mentioned issues with the cookies manager.

3 Likes

I was just struggling with the same issues as everyone, can’t believe you just updated!
Will give this update a try. Thanks Mohamed.

1 Like

Ok so the updated version didn’t fix the problem I was having, with the functions working only some times.

after each “get”, “set” or “delete” call with the cookie_manager I added time.sleep(1) and this fixed it for me!

4 Likes

Hi. Your advice is right. The thing is that js script process method to long to set cookie and this is why it helping, hope one day streamlit will add in base methods their own cookie manager. And it is enough to add delay 1 sec just for set method , others work fine in my case. At any case thank you for share your case.

2 Likes

I’ve tried the CookieManager and was able to set and get cokies with latest version 0.1.70 but ran into similar problems lilke @rickspada , When I restart streamlip app, the cookies are avaiable in browser but not being read by the CookieManager.

1 Like

Thank for the update! How can I set secure or encrypted? I tried setting secure=1 in set but it is unknown as an option.

1 Like

Argh, running into the 4kb cookie limit. Would be nice if it could throw an error if the cookie write failed (I did not see any fail message, just my cookie not being updated if it would have gone over the 4KB limit.)

I could store into a database but with Streamlit closing sessions early (especially on mobile) a sessionID would not be enough identification. Hmm Maybe localStorage.

Interestingly, the lower you go the less consistent it seems to be (at least on Azure Containerapp / Web Apps). However, keeping it at time.sleep(1) for an authentication flow is almost unfeasible. This is the biggest pain point of the current cookie manager and really makes me want to move away from streamlit for everything that needs to be protected by authentication :confused:

@Mohamed, I am setting cookie like cookie_manager.set(“access_token”, access_token, key=1). I noticed that cookie is not getting cleared when session is opened in private window or a new browser. Is this expected behavior or a bug? Shouldn’t the cookie be cleared when opening session in new incognito tab?

This is exactly what I am seeing- multiple runs before it picks anything up, and that kills my application.