AxiosError: Request failed with status code 403 when uploading a file with Streamlit

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

2 Likes

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.

  1. Confirm the cause

XSRF cookies are restricted inside the Spaces iframe. Streamlit’s uploader then rejects the final POST with 403. (Hugging Face)

  1. 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)

  1. 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)

  1. 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)

  1. Ignore enableCORS for this error

403 on upload is almost always XSRF, not CORS, when embedded or proxied. (Streamlit)

  1. 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)

  1. 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)

  1. 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)

  1. 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)

1 Like

Adding it to the docker intialization solved the issue, seems like the config was not being read at all. Thanks!

1 Like

Great! Congrats.

This topic was automatically closed 12 hours after the last reply. New replies are no longer allowed.