I have been facing this error and even after checking similar discussions and adding enableXsrfProtection false
to my config.toml
file, I keep getting this. The upload bar fills up completely but it raises the error afterwards. In some discussions on Streamlit forums people also recommended adding enableCORS = false
to the config, which I did but with no result. Tried it in incognito mode but also doesn’t work. Any idea on what might be causing this? If necessary I can provide the files to debug
This issue has existed for quite some time, and there is no known solution. Existing workarounds also do not work.
I first asked the AI to summarize the workarounds currently known to address this issue. I will use this as a starting point to explore possible solutions.
Do these steps in order.
- Confirm the cause
XSRF cookies are restricted inside the Spaces iframe. Streamlit’s uploader then rejects the final POST with 403. (Hugging Face)
- Verify your app actually disabled XSRF
Add to your app and check on the deployed Space:
import streamlit as st
st.write("XSRF:", st.get_option("server.enableXsrfProtection"))
It must show False
. If it shows True
, your config is not loaded. The config file must be at .streamlit/config.toml
in the same working directory where streamlit run
executes. (Streamlit document)
- If you use the Streamlit SDK Space (no Docker)
Create .streamlit/config.toml
:
[server]
enableXsrfProtection = false
# optional if you test large files:
# maxUploadSize = 400
Redeploy, then re-check step 2. Max upload defaults to 200 MB; increase only if needed. (Streamlit document)
- If you use a Docker Space
Start Streamlit with flags so the setting is guaranteed:
# Dockerfile (tail)
EXPOSE 8501
CMD streamlit run /app/app.py --server.port=8501 --server.address=0.0.0.0 --server.enableXsrfProtection=false
Spaces’ Streamlit guide shows the SDK and deployment pattern; running on 8501 is standard. (Hugging Face)
- Ignore
enableCORS
for this error
403 on upload is almost always XSRF, not CORS, when embedded or proxied. (Streamlit)
- Retest with a tiny file
This isolates XSRF from size issues. If large files fail only due to size, raise server.maxUploadSize
as in step 3. (Streamlit document)
- If you’re behind auth or a reverse proxy
Azure AD and some proxies strip or alter the _xsrf
cookie. Either keep XSRF off or ensure cookies pass through with proper attributes. (GitHub)
- Version sanity check
If you’re on 1.30.x and still see 403 locally or elsewhere, upgrade to a newer Streamlit release; some users report 1.31.0+ resolved their 403. (Streamlit)
- If the page was stale
A stale client cookie can mismatch after redeploys. Hard refresh after redeploys if you still see 403. (Streamlit)
Copy-paste samples you can deploy:
A) SDK Space
# .streamlit/config.toml
[server]
enableXsrfProtection = false
# app.py
import streamlit as st
st.write("XSRF:", st.get_option("server.enableXsrfProtection"))
f = st.file_uploader("Upload any file")
if f:
data = f.getvalue()
st.write({"name": f.name, "size_bytes": len(data)})
B) Docker Space
FROM python:3.11-slim
RUN pip install --no-cache-dir streamlit==1.38.0
WORKDIR /app
COPY app.py /app/app.py
EXPOSE 8501
CMD streamlit run /app/app.py --server.port=8501 --server.address=0.0.0.0 --server.enableXsrfProtection=false
This sequence fixes the 403 in Spaces by ensuring XSRF is actually disabled and verified at runtime. (Hugging Face, Streamlit document)
Adding it to the docker intialization solved the issue, seems like the config was not being read at all. Thanks!
Great! Congrats.
This topic was automatically closed 12 hours after the last reply. New replies are no longer allowed.